AX Agent 컨텍스트 토큰 hover 라벨 닫힘 및 정보 표시 정리
Some checks failed
Release Gate / gate (push) Has been cancelled

- 하단 컨텍스트 토큰 popup 닫힘 판정을 IsMouseOver 중심에서 실제 마우스 좌표 기준으로 보강
- 마우스를 떼었는데도 hover 라벨이 남아 있던 문제를 줄이도록 card/popup 경계 검사 로직 정리
- popup 내용에서 모델명 및 오늘 사용량 줄을 제거하고 현재 사용량과 자동 압축 기준만 남겨 정보 밀도 단순화
- README 및 DEVELOPMENT 문서에 2026-04-05 23:38 (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 20:50:51 +09:00
parent 25031d655d
commit 87c05720ce
3 changed files with 27 additions and 26 deletions

View File

@@ -18939,19 +18939,9 @@ private static (string icon, string label, string bgHex, string fgHex) GetDecisi
TokenUsageArc.Stroke = progressBrush;
TokenUsageThresholdMarker.Fill = progressBrush;
var percentText = $"{Math.Round(usageRatio * 100):0}%";
var (currentService, currentModel) = _llm.GetCurrentModelInfo();
var todayUsage = Services.UsageStatisticsService.GetTodaySnapshot();
var currentModelUsageKey = BuildUsageModelKey(currentService, currentModel);
var currentModelPromptTokens = GetUsageValue(todayUsage.ModelPromptTokens, currentModelUsageKey);
var currentModelCompletionTokens = GetUsageValue(todayUsage.ModelCompletionTokens, currentModelUsageKey);
var currentModelTotalTokens = currentModelPromptTokens + currentModelCompletionTokens;
TokenUsagePercentText.Text = percentText;
TokenUsageSummaryText.Text = $"컨텍스트 {percentText}";
TokenUsageHintText.Text =
$"{Services.TokenEstimator.Format(currentTokens)} / {Services.TokenEstimator.Format(maxContextTokens)}" +
(currentModelTotalTokens > 0
? $" · 오늘 {FormatTokenCount(currentModelTotalTokens)}"
: "");
TokenUsageHintText.Text = $"{Services.TokenEstimator.Format(currentTokens)} / {Services.TokenEstimator.Format(maxContextTokens)}";
CompactNowLabel.Text = compactLabel;
if (TokenUsagePopupTitle != null)
@@ -18960,24 +18950,13 @@ private static (string icon, string label, string bgHex, string fgHex) GetDecisi
TokenUsagePopupUsage.Text = $"{Services.TokenEstimator.Format(currentTokens)}/{Services.TokenEstimator.Format(maxContextTokens)}";
if (TokenUsagePopupDetail != null)
{
var usageLine = currentModelTotalTokens > 0
? $"{currentService} · {currentModel} 오늘 {FormatTokenCount(currentModelTotalTokens)}"
: $"{summary} · 오늘 모델 사용량 없음";
var compactLine = _pendingPostCompaction
TokenUsagePopupDetail.Text = _pendingPostCompaction
? "compact 후 첫 응답 대기 중"
: $"자동 압축 시작 {triggerPercent}%";
TokenUsagePopupDetail.Text = $"{usageLine}\n{compactLine}";
}
if (TokenUsagePopupCompact != null)
{
var compactText = compactLabel switch
{
"지금 압축" => "지금 압축이 필요합니다",
"압축 권장" => "곧 자동 압축이 시작됩니다",
"미리 압축" => "여유가 있을 때 먼저 압축할 수 있습니다",
_ => "AX Agent가 컨텍스트를 자동으로 관리합니다",
};
TokenUsagePopupCompact.Text = compactText;
TokenUsagePopupCompact.Text = "AX Agent가 컨텍스트를 자동으로 관리합니다";
}
TokenUsageCard.ToolTip = null;
@@ -19016,12 +18995,29 @@ private static (string icon, string label, string bgHex, string fgHex) GetDecisi
if (TokenUsagePopup == null)
return;
var cardHovered = TokenUsageCard?.IsMouseOver ?? false;
var popupHovered = TokenUsagePopup.Child is FrameworkElement popupChild && popupChild.IsMouseOver;
var cardHovered = IsMouseInsideElement(TokenUsageCard);
var popupHovered = TokenUsagePopup.Child is FrameworkElement popupChild && IsMouseInsideElement(popupChild);
if (!cardHovered && !popupHovered)
TokenUsagePopup.IsOpen = false;
}
private static bool IsMouseInsideElement(FrameworkElement? element)
{
if (element == null || !element.IsVisible || element.ActualWidth <= 0 || element.ActualHeight <= 0)
return false;
try
{
var mouse = System.Windows.Forms.Control.MousePosition;
var point = element.PointFromScreen(new Point(mouse.X, mouse.Y));
return point.X >= 0 && point.Y >= 0 && point.X <= element.ActualWidth && point.Y <= element.ActualHeight;
}
catch
{
return element.IsMouseOver;
}
}
private static string BuildUsageModelKey(string? service, string? model)
{
var normalizedService = (service ?? "").Trim().ToLowerInvariant();