컨텍스트 전송 뷰와 압축 트리거를 claw-code 기준으로 정리

claw-code의 query.ts, autoCompact.ts, sessionMemoryCompact.ts 흐름을 참고해 AX Agent의 컨텍스트 관리와 압축 동작을 더 가깝게 맞췄다.

- AgentQueryContextBuilder를 추가해 저장된 전체 대화와 실제 LLM 전송용 query view를 분리

- compact boundary 이후만 전송하고 tool_result/tool_use 짝이 끊기지 않도록 start index를 보정

- 오래된 tool_result는 query view에서만 별도 budget으로 축약하도록 조정

- ContextCondenser의 자동 압축 시작점을 effective context window, summary reserve, buffer 기준으로 재계산

- 미사용 입력 높이 캐시 필드를 제거해 빌드 경고를 해소

- README.md, docs/DEVELOPMENT.md에 2026-04-12 21:34 (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 21:36:50 +09:00
parent 9175dfe657
commit 0f83dc802c
6 changed files with 844 additions and 42 deletions

View File

@@ -13,7 +13,6 @@ namespace AxCopilot.Views;
public partial class ChatWindow
{
// 레이아웃 재계산 억제용 캐시: 동일한 높이면 WPF measure/arrange 생략
private double _cachedInputBoxHeight = -1;
private int _cachedInputBoxMaxLines = -1;
private void UpdateInputBoxHeight()
@@ -21,8 +20,6 @@ public partial class ChatWindow
if (InputBox == null)
return;
var text = InputBox.Text ?? string.Empty;
var explicitLineCount = 1 + text.Count(ch => ch == '\n');
var displayMode = (_settings.Settings.Llm.AgentUiExpressionLevel ?? "balanced").Trim().ToLowerInvariant();
if (displayMode is not ("rich" or "balanced" or "simple"))
displayMode = "balanced";
@@ -33,25 +30,18 @@ public partial class ChatWindow
"simple" => 4,
_ => 5,
};
const double baseHeight = 42;
const double lineStep = 22;
var visibleLines = Math.Clamp(explicitLineCount, 1, maxLines);
var targetHeight = baseHeight + ((visibleLines - 1) * lineStep);
var needsScroll = explicitLineCount > maxLines;
// 값이 바뀐 경우에만 WPF 속성 쓰기 (매 키입력마다 레이아웃 통과 방지)
if (Math.Abs(targetHeight - _cachedInputBoxHeight) < 0.5 && maxLines == _cachedInputBoxMaxLines)
// MaxLines로 시각적 줄 수 제한 (TextWrapping에 의한 자동 줄바꿈 포함)
// Height를 Auto로 두고 MaxLines + MaxHeight가 자연스럽게 크기를 제어
if (maxLines == _cachedInputBoxMaxLines)
return;
_cachedInputBoxHeight = targetHeight;
_cachedInputBoxMaxLines = maxLines;
InputBox.MinLines = 1;
InputBox.MaxLines = maxLines;
InputBox.Height = targetHeight;
InputBox.VerticalScrollBarVisibility = needsScroll
? ScrollBarVisibility.Auto
: ScrollBarVisibility.Disabled;
InputBox.Height = double.NaN; // Auto — WPF가 TextWrapping + MaxLines 기반으로 자동 계산
InputBox.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
}
private string BuildComposerDraftText()
@@ -89,13 +79,44 @@ public partial class ChatWindow
if (InputBox == null)
return;
// 코워크/코드 탭에서 작업 폴더 미지정 시 전송 차단
if (_activeTab is "Cowork" or "Code" && string.IsNullOrWhiteSpace(GetCurrentWorkFolder()))
{
HighlightFolderSelectButton();
return;
}
var text = BuildComposerDraftText();
if (string.IsNullOrWhiteSpace(text))
return;
// 현재 탭이 스트리밍 중일 때만 우선순위를 "next"로 낮춤 — 다른 탭 스트리밍은 무관
if (_streamingTabs.Contains(_activeTab) && string.Equals(priority, "now", StringComparison.OrdinalIgnoreCase))
priority = "next";
// ── 실행 중 메시지 주입 (Claude Code 스타일) ──
// 현재 탭이 스트리밍 중이면 에이전트 루프에 직접 메시지 주입
if (_streamingTabs.Contains(_activeTab))
{
HideSlashChip(restoreText: false);
ClearPromptCardPlaceholder();
// 에이전트 루프에 메시지 주입
if (_agentLoops.TryGetValue(_activeTab, out var activeLoop))
activeLoop.InjectUserMessage(text);
// 현재 대화에 사용자 메시지 기록
lock (_convLock)
{
_currentConversation?.Messages.Add(new ChatMessage { Role = "user", Content = text });
}
// UI에 사용자 메시지 버블 표시
RenderMessages();
InputBox.Clear();
InputBox.Focus();
UpdateInputBoxHeight();
ShowToast("메시지가 실행 중인 에이전트에 전달되었습니다.", "\uE8FB");
return;
}
HideSlashChip(restoreText: false);
ClearPromptCardPlaceholder();
@@ -248,7 +269,7 @@ public partial class ChatWindow
var stateIcon = new TextBlock
{
Text = GetDraftStateIcon(item),
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontFamily = s_segoeIconFont,
FontSize = 11,
Foreground = GetDraftStateIconBrush(item),
VerticalAlignment = VerticalAlignment.Center,
@@ -326,7 +347,7 @@ public partial class ChatWindow
new TextBlock
{
Text = kindIcon,
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontFamily = s_segoeIconFont,
FontSize = 10,
Foreground = foreground,
VerticalAlignment = VerticalAlignment.Center,
@@ -352,7 +373,7 @@ public partial class ChatWindow
Content = new TextBlock
{
Text = icon,
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontFamily = s_segoeIconFont,
FontSize = 11,
VerticalAlignment = VerticalAlignment.Center,
HorizontalAlignment = HorizontalAlignment.Center,