From 45779f8c6f84fdffec395fd62980d49315dac8bc Mon Sep 17 00:00:00 2001 From: lacvet Date: Sat, 4 Apr 2026 23:29:45 +0900 Subject: [PATCH] =?UTF-8?q?=EC=BB=A8=ED=85=8D=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=95=95=EC=B6=95=20=EC=9D=B4=EB=A0=A5=20=EC=9E=AC=EB=85=B8?= =?UTF-8?q?=EC=B6=9C=EA=B3=BC=20compact=20=EB=B9=84=EA=B5=90=20=EA=B8=B0?= =?UTF-8?q?=EB=B0=98=20=EB=B3=B4=EA=B0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - AX Agent 하단 컨텍스트 카드 툴팁에 최근 압축 시각, 자동/수동 여부, 압축 전후 토큰, 절감량을 다시 볼 수 있는 compact 이력을 추가함 - 수동 /compact와 전송 전 자동 컨텍스트 압축이 모두 같은 compaction 통계 기록 경로를 사용하도록 정리해 결과를 이후 UI에서도 확인할 수 있게 보강함 - README와 docs/DEVELOPMENT.md에 2026-04-04 23:28 (KST) 기준 이력을 반영함 - 검증: dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify\\ -p:IntermediateOutputPath=obj\\verify\\ (경고 0 / 오류 0) --- README.md | 4 ++++ docs/DEVELOPMENT.md | 7 ++++++ src/AxCopilot/Views/ChatWindow.xaml.cs | 30 +++++++++++++++++++++++++- 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8f8ee44..4b2aca7 100644 --- a/README.md +++ b/README.md @@ -384,6 +384,10 @@ ow + toggle 시각 언어로 통일했습니다. - AX Agent 설정 저장 경로에서 표현 수준을 `rich`로 고정 덮어쓰던 처리도 제거해, 사용자가 선택한 `풍부하게 / 적절하게 / 간단하게` 값이 다른 설정 저장 흐름에서도 유지되도록 보정했습니다. - DraftQueue 패널은 실행 중 / 다음 작업 / 보류 / 완료 / 실패를 개별 섹션으로 나눠 현재 실행 상태와 최근 결과를 더 빠르게 파악할 수 있도록 재구성했습니다. - 검증: `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify\\ -p:IntermediateOutputPath=obj\\verify\\` 경고 0 / 오류 0 +- 업데이트: 2026-04-04 23:28 (KST) +- AX Agent 하단 컨텍스트 카드 툴팁에 최근 압축 이력을 추가해 마지막 자동/수동 compact 시각, 압축 전후 토큰, 실제 절감량을 다시 확인할 수 있게 했습니다. +- 수동 `/compact` 실행과 전송 전 자동 컨텍스트 압축 모두 같은 compaction 통계 경로를 타도록 맞춰, compact 결과를 일회성 토스트가 아니라 이후 UI에서도 계속 확인할 수 있도록 보강했습니다. +- 검증: `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify\\ -p:IntermediateOutputPath=obj\\verify\\` 경고 0 / 오류 0 --- diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index ef63ede..d8aa1b3 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -4076,3 +4076,10 @@ ow + toggle 시각 언어로 다시 정렬했다. - AX Agent 설정 저장 경로와 구형 Agent 설정창에서 표현 수준을 무조건 `rich`로 덮어쓰던 코드를 제거해, 사용자가 선택한 `풍부하게 / 적절하게 / 간단하게` 값이 다른 설정 흐름에서도 유지되도록 수정했다. - DraftQueue 패널은 기존 `실행 대기 / 최근 결과` 묶음에서 `실행 중 / 다음 작업 / 보류 / 완료 / 실패` 개별 섹션 구조로 재편해 queue state가 많은 경우에도 현재 진행, 다음 실행, 재시도 대기, 완료/실패 이력을 더 빠르게 구분할 수 있게 했다. - 검증: dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\verify\ -p:IntermediateOutputPath=obj\verify\ (경고 0 / 오류 0) + +### 2026-04-04 추가 진행 기록 (연속 실행 77차: compact 결과 재노출과 압축 비교 준비) +- 업데이트: 2026-04-04 23:28 (KST) +- AX Agent 하단 컨텍스트 카드의 툴팁에 최근 compact 이력을 추가해 마지막 자동/수동 압축 시각, 압축 전후 토큰 수, 절감량을 이후에도 다시 확인할 수 있게 보강했다. +- 수동 `/compact`와 전송 전 자동 컨텍스트 압축이 모두 같은 `RecordCompactionStats(...)` 경로를 사용하도록 맞춰, 압축 결과가 일회성 상태 메시지에만 머물지 않고 UI에서 재참조 가능하도록 정리했다. +- 이번 라운드부터 `claude-code`의 compact 소스를 기준으로 `session memory compaction → microcompact → context collapse/snip → autocompact → post-compaction 계측` 흐름을 AX 기준과 비교 분석할 준비를 진행했다. +- 검증: 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/Views/ChatWindow.xaml.cs b/src/AxCopilot/Views/ChatWindow.xaml.cs index 1d7e687..0c150aa 100644 --- a/src/AxCopilot/Views/ChatWindow.xaml.cs +++ b/src/AxCopilot/Views/ChatWindow.xaml.cs @@ -95,6 +95,10 @@ public partial class ChatWindow : Window private StackPanel? _selectedMessageActionBar; private Border? _selectedMessageBorder; private bool _isRefreshingFromSettings; + private int? _lastCompactionBeforeTokens; + private int? _lastCompactionAfterTokens; + private DateTime? _lastCompactionAt; + private bool _lastCompactionWasAutomatic; private void ApplyQuickActionVisual(Button button, bool active, string activeBg, string activeFg) { if (button?.Content is not string text) @@ -6507,6 +6511,7 @@ public partial class ChatWindow : Window true, CancellationToken.None); var afterTokens = Services.TokenEstimator.EstimateMessages(working); + RecordCompactionStats(beforeTokens, afterTokens, wasAutomatic: false); if (condensed) { @@ -6543,6 +6548,7 @@ public partial class ChatWindow : Window if (StatusTokens != null) StatusTokens.Text = $"컨텍스트 {Services.TokenEstimator.Format(beforeTokens)} → {Services.TokenEstimator.Format(afterTokens)}"; SetStatus(condensed ? "컨텍스트 압축 완료" : "압축할 컨텍스트 없음", spinning: false); + RefreshContextUsageVisual(); RefreshConversationList(); UpdateTaskSummaryIndicators(); } @@ -8075,6 +8081,7 @@ public partial class ChatWindow : Window // ── 전송 전 컨텍스트 사전 압축 ── { var llm = _settings.Settings.Llm; + var beforeCompactTokens = Services.TokenEstimator.EstimateMessages(sendMessages); var condensed = await ContextCondenser.CondenseIfNeededAsync( sendMessages, _llm, @@ -8084,7 +8091,12 @@ public partial class ChatWindow : Window false, _streamCts!.Token); if (condensed) + { + var afterCompactTokens = Services.TokenEstimator.EstimateMessages(sendMessages); + RecordCompactionStats(beforeCompactTokens, afterCompactTokens, wasAutomatic: true); SetStatus("컨텍스트를 사전 정리했습니다", spinning: true); + RefreshContextUsageVisual(); + } } // ── 자동 모델 라우팅 ── @@ -16481,12 +16493,20 @@ private static (string icon, string label, string bgHex, string fgHex) GetDecisi TokenUsageSummaryText.Text = $"컨텍스트 {percentText}"; TokenUsageHintText.Text = $"{Services.TokenEstimator.Format(currentTokens)} / {Services.TokenEstimator.Format(maxContextTokens)}"; CompactNowLabel.Text = compactLabel; + var compactHistory = _lastCompactionAt.HasValue && _lastCompactionBeforeTokens.HasValue && _lastCompactionAfterTokens.HasValue + ? $"\n최근 압축: {(_lastCompactionWasAutomatic ? "자동" : "수동")} · {_lastCompactionAt.Value:HH:mm:ss}\n" + + $"절감: {_lastCompactionBeforeTokens.Value:N0} → {_lastCompactionAfterTokens.Value:N0} tokens " + + $"(-{Math.Max(0, _lastCompactionBeforeTokens.Value - _lastCompactionAfterTokens.Value):N0}, " + + $"{Services.TokenEstimator.Format(_lastCompactionBeforeTokens.Value)} → {Services.TokenEstimator.Format(_lastCompactionAfterTokens.Value)})" + : ""; + TokenUsageCard.ToolTip = $"상태: {summary}\n" + $"사용량: {currentTokens:N0} / {maxContextTokens:N0} tokens ({percentText})\n" + $"간단 표기: {Services.TokenEstimator.Format(currentTokens)} / {Services.TokenEstimator.Format(maxContextTokens)}\n" + $"자동 압축 시작: {triggerPercent}%\n" + - $"현재 입력 초안 포함"; + $"현재 입력 초안 포함" + + compactHistory; UpdateCircularUsageArc(TokenUsageArc, usageRatio, 18, 18, 14); PositionThresholdMarker(TokenUsageThresholdMarker, triggerRatio, 18, 18, 14, 3); @@ -16535,6 +16555,14 @@ private static (string icon, string label, string bgHex, string fgHex) GetDecisi centerY + radius * Math.Sin(radians)); } + private void RecordCompactionStats(int beforeTokens, int afterTokens, bool wasAutomatic) + { + _lastCompactionBeforeTokens = Math.Max(0, beforeTokens); + _lastCompactionAfterTokens = Math.Max(0, afterTokens); + _lastCompactionAt = DateTime.Now; + _lastCompactionWasAutomatic = wasAutomatic; + } + private void ScheduleGitBranchRefresh(int delayMs = 400) { if (BtnGitBranch == null)