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:
2026-04-12 22:32:40 +09:00
parent 58b798d3e4
commit da11029284
7 changed files with 215 additions and 27 deletions

View File

@@ -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;