Initial commit to new repository
This commit is contained in:
209
.decompiledproj/AxCopilot/Services/Agent/ProjectRulesService.cs
Normal file
209
.decompiledproj/AxCopilot/Services/Agent/ProjectRulesService.cs
Normal file
@@ -0,0 +1,209 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace AxCopilot.Services.Agent;
|
||||
|
||||
public static class ProjectRulesService
|
||||
{
|
||||
public class ProjectRule
|
||||
{
|
||||
public string FilePath { get; set; } = "";
|
||||
|
||||
public string Name { get; set; } = "";
|
||||
|
||||
public string Description { get; set; } = "";
|
||||
|
||||
public string AppliesTo { get; set; } = "";
|
||||
|
||||
public string When { get; set; } = "always";
|
||||
|
||||
public string Body { get; set; } = "";
|
||||
}
|
||||
|
||||
private static readonly Regex FrontMatterRegex = new Regex("^---\\s*\\n(.*?)\\n---\\s*\\n", RegexOptions.Compiled | RegexOptions.Singleline);
|
||||
|
||||
private static readonly Regex YamlKeyValue = new Regex("^\\s*(\\w[\\w-]*)\\s*:\\s*(.+?)\\s*$", RegexOptions.Multiline | RegexOptions.Compiled);
|
||||
|
||||
public static List<ProjectRule> LoadRules(string workFolder)
|
||||
{
|
||||
List<ProjectRule> list = new List<ProjectRule>();
|
||||
if (string.IsNullOrEmpty(workFolder))
|
||||
{
|
||||
return list;
|
||||
}
|
||||
string text = FindRulesDirectory(workFolder);
|
||||
if (text == null)
|
||||
{
|
||||
return list;
|
||||
}
|
||||
try
|
||||
{
|
||||
string[] files = Directory.GetFiles(text, "*.md");
|
||||
foreach (string filePath in files)
|
||||
{
|
||||
ProjectRule projectRule = ParseRuleFile(filePath);
|
||||
if (projectRule != null)
|
||||
{
|
||||
list.Add(projectRule);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static List<ProjectRule> FilterRules(List<ProjectRule> rules, string when = "always", IEnumerable<string>? filePaths = null)
|
||||
{
|
||||
List<ProjectRule> list = new List<ProjectRule>();
|
||||
foreach (ProjectRule rule in rules)
|
||||
{
|
||||
string text = rule.When.ToLowerInvariant().Trim();
|
||||
if (text != "always" && text != when.ToLowerInvariant())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(rule.AppliesTo) && filePaths != null)
|
||||
{
|
||||
string pattern = rule.AppliesTo.Trim();
|
||||
if (!filePaths.Any((string fp) => MatchesGlob(fp, pattern)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
list.Add(rule);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static string FormatForSystemPrompt(List<ProjectRule> rules)
|
||||
{
|
||||
if (rules.Count == 0)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
stringBuilder.AppendLine("\n## 프로젝트 규칙 (.ax/rules/)");
|
||||
stringBuilder.AppendLine("아래 규칙을 반드시 준수하세요:\n");
|
||||
foreach (ProjectRule rule in rules)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(rule.Name))
|
||||
{
|
||||
StringBuilder stringBuilder2 = stringBuilder;
|
||||
StringBuilder stringBuilder3 = stringBuilder2;
|
||||
StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(4, 1, stringBuilder2);
|
||||
handler.AppendLiteral("### ");
|
||||
handler.AppendFormatted(rule.Name);
|
||||
stringBuilder3.AppendLine(ref handler);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(rule.Description))
|
||||
{
|
||||
StringBuilder stringBuilder2 = stringBuilder;
|
||||
StringBuilder stringBuilder4 = stringBuilder2;
|
||||
StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(3, 1, stringBuilder2);
|
||||
handler.AppendLiteral("*");
|
||||
handler.AppendFormatted(rule.Description);
|
||||
handler.AppendLiteral("*\n");
|
||||
stringBuilder4.AppendLine(ref handler);
|
||||
}
|
||||
stringBuilder.AppendLine(rule.Body.Trim());
|
||||
stringBuilder.AppendLine();
|
||||
}
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
|
||||
internal static string? FindRulesDirectory(string workFolder)
|
||||
{
|
||||
string text = workFolder;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (string.IsNullOrEmpty(text))
|
||||
{
|
||||
break;
|
||||
}
|
||||
string text2 = Path.Combine(text, ".ax", "rules");
|
||||
if (Directory.Exists(text2))
|
||||
{
|
||||
return text2;
|
||||
}
|
||||
text = Directory.GetParent(text)?.FullName;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
internal static ProjectRule? ParseRuleFile(string filePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
string text = File.ReadAllText(filePath, Encoding.UTF8);
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
ProjectRule projectRule = new ProjectRule
|
||||
{
|
||||
FilePath = filePath,
|
||||
Name = Path.GetFileNameWithoutExtension(filePath)
|
||||
};
|
||||
Match match = FrontMatterRegex.Match(text);
|
||||
if (match.Success)
|
||||
{
|
||||
string value = match.Groups[1].Value;
|
||||
foreach (Match item in YamlKeyValue.Matches(value))
|
||||
{
|
||||
string text2 = item.Groups[1].Value.ToLowerInvariant();
|
||||
string text3 = item.Groups[2].Value.Trim().Trim('"', '\'');
|
||||
switch (text2)
|
||||
{
|
||||
case "name":
|
||||
projectRule.Name = text3;
|
||||
break;
|
||||
case "description":
|
||||
projectRule.Description = text3;
|
||||
break;
|
||||
case "applies-to":
|
||||
case "appliesto":
|
||||
projectRule.AppliesTo = text3;
|
||||
break;
|
||||
case "when":
|
||||
projectRule.When = text3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
string text4 = text;
|
||||
int num = match.Index + match.Length;
|
||||
projectRule.Body = text4.Substring(num, text4.Length - num);
|
||||
}
|
||||
else
|
||||
{
|
||||
projectRule.Body = text;
|
||||
}
|
||||
return string.IsNullOrWhiteSpace(projectRule.Body) ? null : projectRule;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool MatchesGlob(string path, string pattern)
|
||||
{
|
||||
if (pattern.StartsWith("*."))
|
||||
{
|
||||
string text = pattern;
|
||||
return path.EndsWith(text.Substring(1, text.Length - 1), StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
if (pattern.StartsWith("**/"))
|
||||
{
|
||||
string text = pattern;
|
||||
string pattern2 = text.Substring(3, text.Length - 3);
|
||||
return MatchesGlob(Path.GetFileName(path), pattern2);
|
||||
}
|
||||
return Path.GetFileName(path).Equals(pattern, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user