- AgentMemoryService frontmatter에 enabled와 tags 메타를 추가해 규칙 파일을 비활성 상태로 보관하거나 태그 단위로 묶어 관리할 수 있도록 확장 - enabled:false 규칙은 로드 단계에서 제외하도록 처리해 실험용 메모리 규칙을 안전하게 보관 가능하게 정리 - MemoryTool list/search 출력에 tags 메타를 함께 노출해 규칙 설명·적용 경로·우선순위와 함께 묶음 성격까지 바로 읽을 수 있도록 개선 - 설정의 메모리 편집 다이얼로그 frontmatter 예시를 description/enabled/tags/paths 기준으로 갱신해 현재 지원 메타를 UI에서도 바로 참고 가능하게 정리 - README 및 DEVELOPMENT 문서에 2026-04-07 00:52 (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:
@@ -1411,3 +1411,6 @@ MIT License
|
||||
- 업데이트: 2026-04-07 00:45 (KST)
|
||||
- AX Copilot 메인 설정의 에이전트 메모리 영역에서 `관리형 / 사용자 / 프로젝트 / 로컬` 메모리 파일을 직접 열어 수정할 수 있게 했습니다. [SettingsWindow.xaml](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/SettingsWindow.xaml), [SettingsWindow.xaml.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/SettingsWindow.xaml.cs)에 계층형 메모리 편집 버튼과 전용 편집 다이얼로그를 추가했습니다.
|
||||
- 메모리 편집 다이얼로그는 현재 테마를 따르는 안내 패널과 멀티라인 편집기를 제공하고, `description`/`paths` frontmatter 예시를 바로 볼 수 있습니다. 저장 시 해당 scope 파일을 즉시 갱신하고, 빈 내용으로 저장하면 파일을 삭제한 뒤 메모리 계층을 다시 로드합니다.
|
||||
- 업데이트: 2026-04-07 00:52 (KST)
|
||||
- 계층형 메모리 frontmatter를 더 확장해 `enabled:`와 `tags:`를 지원하도록 했습니다. 이제 실험용 규칙을 파일에 남겨둔 채 비활성화할 수 있고, 규칙 묶음을 태그 단위로 구분해 관리할 수 있습니다.
|
||||
- [AgentMemoryService.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Services/AgentMemoryService.cs)는 `enabled: false`인 규칙 파일을 메모리 계층에서 제외하고, [MemoryTool.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Services/Agent/MemoryTool.cs)의 `list/search` 결과에는 `tags` 메타를 함께 보여줘 어떤 규칙군인지 더 빠르게 읽을 수 있게 했습니다.
|
||||
|
||||
@@ -5205,3 +5205,15 @@ ow + toggle ?쒓컖 ?몄뼱濡??ㅼ떆 ?뺣젹?덈떎.
|
||||
- scope별 메모리 파일 경로를 계산해 실제 내용을 읽고 수정할 수 있는 `OpenMemoryScopeEditor(...)`를 추가했다.
|
||||
- 편집 다이얼로그는 현재 테마 색을 사용하고, `description`/`paths` frontmatter 예시를 안내로 보여준다.
|
||||
- 저장 시 해당 scope 메모리 파일을 즉시 갱신하고, 빈 내용이면 파일을 삭제한 뒤 `AgentMemoryService.Load(...)`를 다시 호출해 메모리 계층이 곧바로 반영되도록 했다.
|
||||
|
||||
## 2026-04-07 00:52 (KST)
|
||||
|
||||
- [AgentMemoryService.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Services/AgentMemoryService.cs)
|
||||
- 계층형 메모리 frontmatter에 `enabled:`와 `tags:` 메타를 추가했다.
|
||||
- `enabled: false`인 규칙 파일은 로드 단계에서 제외해 실험용/보관용 규칙을 파일에 남겨둔 채 비활성화할 수 있게 했다.
|
||||
- `tags:`는 `- payments`, `- review` 같은 목록 형식으로 읽어 `MemoryInstructionDocument`에 함께 보관한다.
|
||||
- [MemoryTool.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Services/Agent/MemoryTool.cs)
|
||||
- `list`, `search` 출력에 계층형 메모리 문서의 `tags` 메타를 함께 표시하도록 정리했다.
|
||||
- 사용자는 이제 `/memory` 결과에서 규칙의 설명, 적용 경로, 우선순위뿐 아니라 태그 묶음까지 같이 확인할 수 있다.
|
||||
- [SettingsWindow.xaml.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/SettingsWindow.xaml.cs)
|
||||
- 메모리 편집 다이얼로그의 frontmatter 예시를 `description / enabled / tags / paths` 기준으로 갱신해, 설정 UI에서도 현재 지원 메타 전체를 바로 참고할 수 있게 했다.
|
||||
|
||||
@@ -110,7 +110,8 @@ public class MemoryTool : IAgentTool
|
||||
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)})" : "";
|
||||
sb.AppendLine($" [{doc.Label}] {doc.Path}{priority}{suffix}{scopeHint}");
|
||||
var tags = doc.Tags.Count > 0 ? $" (tags: {string.Join(", ", doc.Tags)})" : "";
|
||||
sb.AppendLine($" [{doc.Label}] {doc.Path}{priority}{suffix}{scopeHint}{tags}");
|
||||
}
|
||||
sb.AppendLine();
|
||||
}
|
||||
@@ -140,7 +141,8 @@ public class MemoryTool : IAgentTool
|
||||
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)})" : "";
|
||||
sb.AppendLine($" • [{doc.Label}] {doc.Path}{priority}{suffix}{scopeHint}");
|
||||
var tags = doc.Tags.Count > 0 ? $" (tags: {string.Join(", ", doc.Tags)})" : "";
|
||||
sb.AppendLine($" • [{doc.Label}] {doc.Path}{priority}{suffix}{scopeHint}{tags}");
|
||||
}
|
||||
sb.AppendLine();
|
||||
}
|
||||
|
||||
@@ -407,6 +407,9 @@ public class AgentMemoryService
|
||||
return;
|
||||
|
||||
var frontMatter = ParseFrontMatter(content);
|
||||
if (!frontMatter.Enabled)
|
||||
return;
|
||||
|
||||
if (frontMatter.Paths.Count > 0 && !ShouldApplyToCurrentWorkFolder(frontMatter.Paths, projectRoot, _currentWorkFolder))
|
||||
return;
|
||||
|
||||
@@ -418,6 +421,8 @@ public class AgentMemoryService
|
||||
Content = frontMatter.Content.Trim(),
|
||||
Paths = frontMatter.Paths,
|
||||
Description = frontMatter.Description,
|
||||
Tags = frontMatter.Tags,
|
||||
Enabled = frontMatter.Enabled,
|
||||
LoadOrder = _instructionDocuments.Count
|
||||
});
|
||||
}
|
||||
@@ -695,11 +700,11 @@ public class AgentMemoryService
|
||||
}
|
||||
}
|
||||
|
||||
private static (string Content, List<string> Paths, string Description) ParseFrontMatter(string content)
|
||||
private static (string Content, List<string> Paths, string Description, List<string> Tags, bool Enabled) ParseFrontMatter(string content)
|
||||
{
|
||||
var lines = content.Replace("\r\n", "\n").Split('\n').ToList();
|
||||
if (lines.Count < 3 || !string.Equals(lines[0].Trim(), "---", StringComparison.Ordinal))
|
||||
return (content, new List<string>(), "");
|
||||
return (content, new List<string>(), "", new List<string>(), true);
|
||||
|
||||
var endIndex = -1;
|
||||
for (var i = 1; i < lines.Count; i++)
|
||||
@@ -712,11 +717,14 @@ public class AgentMemoryService
|
||||
}
|
||||
|
||||
if (endIndex < 1)
|
||||
return (content, new List<string>(), "");
|
||||
return (content, new List<string>(), "", new List<string>(), true);
|
||||
|
||||
var paths = new List<string>();
|
||||
var tags = new List<string>();
|
||||
var description = "";
|
||||
var enabled = true;
|
||||
var inPaths = false;
|
||||
var inTags = false;
|
||||
for (var i = 1; i < endIndex; i++)
|
||||
{
|
||||
var line = lines[i].Trim();
|
||||
@@ -724,11 +732,29 @@ public class AgentMemoryService
|
||||
{
|
||||
description = line["description:".Length..].Trim().Trim('"');
|
||||
inPaths = false;
|
||||
inTags = false;
|
||||
continue;
|
||||
}
|
||||
if (line.StartsWith("enabled:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var raw = line["enabled:".Length..].Trim().Trim('"');
|
||||
enabled = !string.Equals(raw, "false", StringComparison.OrdinalIgnoreCase)
|
||||
&& !string.Equals(raw, "0", StringComparison.OrdinalIgnoreCase)
|
||||
&& !string.Equals(raw, "off", StringComparison.OrdinalIgnoreCase);
|
||||
inPaths = false;
|
||||
inTags = false;
|
||||
continue;
|
||||
}
|
||||
if (line.StartsWith("paths:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
inPaths = true;
|
||||
inTags = false;
|
||||
continue;
|
||||
}
|
||||
if (line.StartsWith("tags:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
inTags = true;
|
||||
inPaths = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -745,10 +771,24 @@ public class AgentMemoryService
|
||||
if (line.Length > 0)
|
||||
inPaths = false;
|
||||
}
|
||||
|
||||
if (inTags)
|
||||
{
|
||||
if (line.StartsWith("-", StringComparison.Ordinal))
|
||||
{
|
||||
var tag = line[1..].Trim().Trim('"');
|
||||
if (!string.IsNullOrWhiteSpace(tag))
|
||||
tags.Add(tag);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.Length > 0)
|
||||
inTags = false;
|
||||
}
|
||||
}
|
||||
|
||||
var stripped = string.Join("\n", lines.Skip(endIndex + 1)).Trim();
|
||||
return (stripped, paths, description);
|
||||
return (stripped, paths, description, tags, enabled);
|
||||
}
|
||||
|
||||
private static bool ShouldApplyToCurrentWorkFolder(IReadOnlyList<string> patterns, string? projectRoot, string? currentWorkFolder)
|
||||
@@ -861,6 +901,12 @@ public class MemoryInstructionDocument
|
||||
[JsonPropertyName("description")]
|
||||
public string Description { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("tags")]
|
||||
public List<string> Tags { get; set; } = new();
|
||||
|
||||
[JsonPropertyName("enabled")]
|
||||
public bool Enabled { get; set; } = true;
|
||||
|
||||
[JsonPropertyName("loadOrder")]
|
||||
public int LoadOrder { get; set; }
|
||||
|
||||
|
||||
@@ -3063,7 +3063,7 @@ public partial class SettingsWindow : Window
|
||||
Margin = new Thickness(0, 0, 0, 12),
|
||||
Child = new TextBlock
|
||||
{
|
||||
Text = "frontmatter 예시:\n---\ndescription: 결제 모듈 규칙\npaths:\n - src/Payments/**\n---\n\n메모리 내용은 /memory 명령과 함께 사용되며, 빈 내용으로 저장하면 파일이 삭제됩니다.",
|
||||
Text = "frontmatter 예시:\n---\ndescription: 결제 모듈 규칙\nenabled: true\ntags:\n - payments\n - review\npaths:\n - src/Payments/**\n---\n\n메모리 내용은 /memory 명령과 함께 사용되며, 빈 내용으로 저장하면 파일이 삭제됩니다.",
|
||||
FontSize = 12,
|
||||
Foreground = subFgBrush,
|
||||
TextWrapping = TextWrapping.Wrap,
|
||||
|
||||
Reference in New Issue
Block a user