compact 뒤 첨부 참조가 이어지도록 요약/경계 메시지를 보강

- ContextCondenser가 오래된 메시지 구간의 첨부 파일 이름과 이미지 개수를 수집해 microcompact boundary와 요약 메시지에 함께 기록
- 요약 메시지에 AttachedFiles를 보존해 compact 이후 query view에서도 파일 참조 continuity가 유지되도록 조정
- README와 DEVELOPMENT 문서에 2026-04-12 22:36 (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:58:55 +09:00
parent d8cd04aa4f
commit b8f4df1892
3 changed files with 66 additions and 13 deletions

View File

@@ -54,6 +54,12 @@ public static class ContextCondenser
public int PreservedToolPairs { get; init; }
}
private sealed class CompactionAttachmentSummary
{
public required List<string> AttachedFiles { get; init; }
public int ImageCount { get; init; }
}
/// <summary>모델별 입력 토큰 한도 (대략).</summary>
private static int GetModelInputLimit(string service, string model)
{
@@ -703,17 +709,7 @@ public static class ContextCondenser
!(m.Content ?? "").StartsWith("{\"_tool_use_blocks\"", StringComparison.Ordinal) &&
m.MetaKind == null);
var attachedFiles = group
.SelectMany(m => m.AttachedFiles ?? Enumerable.Empty<string>())
.Distinct(StringComparer.OrdinalIgnoreCase)
.Select(path =>
{
try { return System.IO.Path.GetFileName(path); }
catch { return path; }
})
.Where(name => !string.IsNullOrWhiteSpace(name))
.Take(4)
.ToList();
var attachmentSummary = CollectCompactionAttachmentSummary(group, 4);
var lines = new List<string>
{
@@ -724,7 +720,8 @@ public static class ContextCondenser
if (toolCalls > 0) lines.Add($"- 도구 호출 {toolCalls}건 정리");
if (metaEvents > 0) lines.Add($"- 실행 메타/로그 {metaEvents}건 정리");
if (longTexts > 0) lines.Add($"- 긴 설명/출력 {longTexts}건 축약");
if (attachedFiles.Count > 0) lines.Add($"- 관련 파일: {string.Join(", ", attachedFiles)}");
if (attachmentSummary.AttachedFiles.Count > 0) lines.Add($"- 관련 파일: {string.Join(", ", attachmentSummary.AttachedFiles)}");
if (attachmentSummary.ImageCount > 0) lines.Add($"- 관련 이미지: {attachmentSummary.ImageCount}개");
return new ChatMessage
{
@@ -733,6 +730,7 @@ public static class ContextCondenser
Timestamp = group.Last().Timestamp,
MetaKind = "microcompact_boundary",
MetaRunId = group.Last().MetaRunId,
AttachedFiles = attachmentSummary.AttachedFiles.Count > 0 ? attachmentSummary.AttachedFiles : null,
};
}
@@ -747,6 +745,7 @@ public static class ContextCondenser
var systemMsg = window.SystemMessage;
var oldMessages = window.OldMessages;
var recentMessages = window.RecentMessages;
var attachmentSummary = CollectCompactionAttachmentSummary(oldMessages, 6);
if (oldMessages.Count < 3) return false;
@@ -787,8 +786,9 @@ public static class ContextCondenser
messages.Add(new ChatMessage
{
Role = "user",
Content = $"[이전 대화 요약 — {oldMessages.Count}개 메시지 압축]\n{summary}",
Content = BuildSummaryMessageContent(oldMessages.Count, summary, attachmentSummary),
Timestamp = DateTime.Now,
AttachedFiles = attachmentSummary.AttachedFiles.Count > 0 ? attachmentSummary.AttachedFiles : null,
});
messages.Add(new ChatMessage
{
@@ -806,4 +806,42 @@ public static class ContextCondenser
return false;
}
}
private static CompactionAttachmentSummary CollectCompactionAttachmentSummary(IEnumerable<ChatMessage> messages, int maxFiles)
{
var attachedFiles = messages
.SelectMany(m => m.AttachedFiles ?? Enumerable.Empty<string>())
.Distinct(StringComparer.OrdinalIgnoreCase)
.Select(path =>
{
try { return System.IO.Path.GetFileName(path); }
catch { return path; }
})
.Where(name => !string.IsNullOrWhiteSpace(name))
.Take(Math.Max(1, maxFiles))
.ToList();
var imageCount = messages.Sum(m => m.Images?.Count ?? 0);
return new CompactionAttachmentSummary
{
AttachedFiles = attachedFiles,
ImageCount = imageCount,
};
}
private static string BuildSummaryMessageContent(int oldMessageCount, string summary, CompactionAttachmentSummary attachmentSummary)
{
var lines = new List<string>
{
$"[이전 대화 요약 — {oldMessageCount}개 메시지 압축]",
summary.Trim()
};
if (attachmentSummary.AttachedFiles.Count > 0)
lines.Add($"참고 파일: {string.Join(", ", attachmentSummary.AttachedFiles)}");
if (attachmentSummary.ImageCount > 0)
lines.Add($"참고 이미지: {attachmentSummary.ImageCount}개");
return string.Join("\n", lines.Where(x => !string.IsNullOrWhiteSpace(x)));
}
}