claude-code 기준 provider 호환성과 compact 후속 흐름을 보강한다
- OpenAI 호환 tool_choice 400 오류에 대한 일반 fallback을 추가하고 Qwen·LLaMA·DeepSeek 계열 vLLM의 도구 호출 프로파일을 더 보수적으로 조정 - compact 이후 branch context와 최근 tool state를 query view에 재주입하고 UI 표현 수준에 맞춰 compact 카드/컨텍스트 사용 팝업/최종 보고 밀도를 세분화 - README와 DEVELOPMENT 문서 이력을 2026-04-12 23:45 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:
@@ -6,7 +6,7 @@ namespace AxCopilot.Views;
|
||||
|
||||
public partial class ChatWindow
|
||||
{
|
||||
// 토큰 추정 캐시: 메시지 수나 대화 ID가 달라질 때만 재계산
|
||||
// 메시지 개수와 대화 ID가 바뀔 때만 재계산한다.
|
||||
private int _cachedMessageTokens;
|
||||
private int _cachedMessageCountForTokens = -1;
|
||||
private string? _cachedConvIdForTokens;
|
||||
@@ -28,6 +28,7 @@ public partial class ChatWindow
|
||||
}
|
||||
|
||||
var llm = _settings.Settings.Llm;
|
||||
var expressionLevel = GetAgentUiExpressionLevel();
|
||||
var maxContextTokens = Math.Clamp(llm.MaxContextTokens, 1024, 1_000_000);
|
||||
var triggerPercent = Math.Clamp(llm.ContextCompactTriggerPercent, 10, 95);
|
||||
var triggerRatio = triggerPercent / 100.0;
|
||||
@@ -45,6 +46,7 @@ public partial class ChatWindow
|
||||
_cachedConvIdForTokens = convId;
|
||||
_cachedMessageCountForTokens = msgCount;
|
||||
}
|
||||
|
||||
messageTokens = _cachedMessageTokens;
|
||||
}
|
||||
|
||||
@@ -52,7 +54,7 @@ public partial class ChatWindow
|
||||
var draftTokens = string.IsNullOrWhiteSpace(draftText) ? 0 : Services.TokenEstimator.Estimate(draftText) + 4;
|
||||
|
||||
var hasAnyMessages = messageTokens > 0 || _isStreaming;
|
||||
int baseOverhead = 0;
|
||||
var baseOverhead = 0;
|
||||
if (hasAnyMessages)
|
||||
{
|
||||
var sysPromptLen = _llm?.SystemPrompt?.Length ?? 0;
|
||||
@@ -118,11 +120,21 @@ public partial class ChatWindow
|
||||
if (TokenUsagePopupUsage != null)
|
||||
TokenUsagePopupUsage.Text = $"{Services.TokenEstimator.Format(currentTokens)}/{Services.TokenEstimator.Format(maxContextTokens)}";
|
||||
if (TokenUsagePopupDetail != null)
|
||||
TokenUsagePopupDetail.Text = detailText;
|
||||
TokenUsagePopupDetail.Text = expressionLevel == "simple"
|
||||
? detailText
|
||||
: $"{detailText} · 임계 {triggerPercent}%";
|
||||
if (TokenUsagePopupCompact != null)
|
||||
{
|
||||
TokenUsagePopupCompact.Text = _sessionCompactionCount > 0
|
||||
? $"누적 압축 {_sessionCompactionCount}회 · 절감 {FormatTokenCount(_sessionCompactionSavedTokens)}"
|
||||
: "AX Agent가 컨텍스트를 자동 관리합니다";
|
||||
? expressionLevel switch
|
||||
{
|
||||
"simple" => $"압축 {_sessionCompactionCount}회 · {FormatTokenCount(_sessionCompactionSavedTokens)} 절감",
|
||||
_ => $"누적 압축 {_sessionCompactionCount}회 · 절감 {FormatTokenCount(_sessionCompactionSavedTokens)}"
|
||||
}
|
||||
: expressionLevel == "rich"
|
||||
? "AX Agent가 컨텍스트를 자동 관리합니다"
|
||||
: "컨텍스트 자동 관리";
|
||||
}
|
||||
|
||||
TokenUsageCard.ToolTip = null;
|
||||
|
||||
|
||||
@@ -350,6 +350,7 @@ public partial class ChatWindow
|
||||
|
||||
private Border CreateCompactionMetaCard(ChatMessage message, Brush primaryText, Brush secondaryText, Brush hintBg, Brush borderBrush, Brush accentBrush)
|
||||
{
|
||||
var expressionLevel = GetAgentUiExpressionLevel();
|
||||
var icon = "\uE9CE";
|
||||
var title = message.MetaKind switch
|
||||
{
|
||||
@@ -399,20 +400,40 @@ public partial class ChatWindow
|
||||
};
|
||||
|
||||
var detailBits = new List<string>();
|
||||
if (message.AttachedFiles?.Count > 0)
|
||||
if (message.AttachedFiles?.Count > 0 && expressionLevel != "simple")
|
||||
detailBits.Add($"파일 {message.AttachedFiles.Count}개");
|
||||
var compactDetail = detailBits.Count > 0
|
||||
? $"{summary} · {string.Join(", ", detailBits)}"
|
||||
: summary;
|
||||
var compactDetail = expressionLevel switch
|
||||
{
|
||||
"simple" => summary,
|
||||
_ when detailBits.Count > 0 => $"{summary} · {string.Join(", ", detailBits)}",
|
||||
_ => summary
|
||||
};
|
||||
|
||||
stack.Children.Add(new TextBlock
|
||||
{
|
||||
Text = compactDetail,
|
||||
FontSize = 10.5,
|
||||
FontSize = expressionLevel == "simple" ? 10 : 10.5,
|
||||
Foreground = secondaryText,
|
||||
TextWrapping = TextWrapping.Wrap,
|
||||
});
|
||||
|
||||
if (expressionLevel == "rich" && !string.IsNullOrWhiteSpace(message.Content))
|
||||
{
|
||||
var preview = message.Content.Trim();
|
||||
if (preview.Length > 120)
|
||||
preview = preview[..120] + "...";
|
||||
|
||||
stack.Children.Add(new TextBlock
|
||||
{
|
||||
Text = preview,
|
||||
FontSize = 10,
|
||||
Foreground = secondaryText,
|
||||
Opacity = 0.88,
|
||||
Margin = new Thickness(0, 6, 0, 0),
|
||||
TextWrapping = TextWrapping.Wrap,
|
||||
});
|
||||
}
|
||||
|
||||
wrapper.Child = stack;
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user