메모리 적용 근거 표시와 감사/명령 UX 마무리
- Cowork와 Code 진행 표시 줄에 메모리 규칙 및 학습 메모리 적용 근거를 함께 노출 - include 감사 로그 최근 3일 필터와 보관 시점 판정을 정리해 메모리 감사 상태를 더 정확히 표시 - /memory list 및 search 출력 형식을 우선순위·레이어·설명·paths·tags 중심으로 재구성하고 Release 빌드 경고/오류 0 검증
This commit is contained in:
@@ -106,13 +106,7 @@ public class MemoryTool : IAgentTool
|
||||
{
|
||||
sb.AppendLine($"계층형 메모리 {docs.Count}개:");
|
||||
foreach (var doc in docs)
|
||||
{
|
||||
var priority = doc.Priority > 0 ? $" (우선순위 {doc.Priority})" : "";
|
||||
var suffix = string.IsNullOrWhiteSpace(doc.Description) ? "" : $" — {doc.Description}";
|
||||
var scopeHint = doc.Paths.Count > 0 ? $" (paths: {string.Join(", ", doc.Paths)})" : "";
|
||||
var tags = doc.Tags.Count > 0 ? $" (tags: {string.Join(", ", doc.Tags)})" : "";
|
||||
sb.AppendLine($" [{doc.Label}] {doc.Path}{priority}{suffix}{scopeHint}{tags}");
|
||||
}
|
||||
sb.AppendLine(FormatInstructionDocument(doc));
|
||||
sb.AppendLine();
|
||||
}
|
||||
|
||||
@@ -137,13 +131,7 @@ public class MemoryTool : IAgentTool
|
||||
{
|
||||
sb.AppendLine($"계층형 메모리 파일 {docs.Count}개:");
|
||||
foreach (var doc in docs)
|
||||
{
|
||||
var priority = doc.Priority > 0 ? $" (우선순위 {doc.Priority})" : "";
|
||||
var suffix = string.IsNullOrWhiteSpace(doc.Description) ? "" : $" — {doc.Description}";
|
||||
var scopeHint = doc.Paths.Count > 0 ? $" (paths: {string.Join(", ", doc.Paths)})" : "";
|
||||
var tags = doc.Tags.Count > 0 ? $" (tags: {string.Join(", ", doc.Tags)})" : "";
|
||||
sb.AppendLine($" • [{doc.Label}] {doc.Path}{priority}{suffix}{scopeHint}{tags}");
|
||||
}
|
||||
sb.AppendLine(FormatInstructionDocument(doc));
|
||||
sb.AppendLine();
|
||||
}
|
||||
|
||||
@@ -217,4 +205,21 @@ public class MemoryTool : IAgentTool
|
||||
|
||||
return ToolResult.Ok($"메모리 파일 경로: {path}\n\n{content}");
|
||||
}
|
||||
|
||||
private static string FormatInstructionDocument(MemoryInstructionDocument doc)
|
||||
{
|
||||
var meta = new List<string>
|
||||
{
|
||||
doc.Priority > 0 ? $"우선순위 {doc.Priority}" : "우선순위 미정",
|
||||
$"layer: {doc.Layer}"
|
||||
};
|
||||
if (!string.IsNullOrWhiteSpace(doc.Description))
|
||||
meta.Add(doc.Description);
|
||||
if (doc.Paths.Count > 0)
|
||||
meta.Add($"paths: {string.Join(", ", doc.Paths)}");
|
||||
if (doc.Tags.Count > 0)
|
||||
meta.Add($"tags: {string.Join(", ", doc.Tags)}");
|
||||
|
||||
return $" • [{doc.Label}] {doc.Path}\n {string.Join(" · ", meta)}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,6 +87,24 @@ public static class AuditLogService
|
||||
return LoadFile(Path.Combine(AuditDir, fileName));
|
||||
}
|
||||
|
||||
/// <summary>최근 N일 내 특정 액션 감사 로그를 최신순으로 읽습니다.</summary>
|
||||
public static List<AuditEntry> LoadRecent(string action, int maxCount = 20, int daysBack = 3)
|
||||
{
|
||||
var since = DateTime.Now.Date.AddDays(-Math.Max(0, daysBack - 1));
|
||||
var entries = new List<AuditEntry>();
|
||||
|
||||
for (var day = DateTime.Now.Date; day >= since; day = day.AddDays(-1))
|
||||
{
|
||||
entries.AddRange(LoadDate(day)
|
||||
.Where(x => string.Equals(x.Action, action, StringComparison.OrdinalIgnoreCase)));
|
||||
}
|
||||
|
||||
return entries
|
||||
.OrderByDescending(x => x.Timestamp)
|
||||
.Take(Math.Max(1, maxCount))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private static List<AuditEntry> LoadFile(string filePath)
|
||||
{
|
||||
var entries = new List<AuditEntry>();
|
||||
@@ -112,7 +130,7 @@ public static class AuditLogService
|
||||
var cutoff = DateTime.Now.AddDays(-retentionDays);
|
||||
foreach (var f in Directory.GetFiles(AuditDir, "*.json"))
|
||||
{
|
||||
if (File.GetCreationTime(f) < cutoff)
|
||||
if (File.GetLastWriteTime(f) < cutoff)
|
||||
File.Delete(f);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user