스킬 런타임 2차 고도화와 도구 노출 필터 정비
프로젝트 .claude/skills 재귀 로드와 namespaced SKILL.md 파싱을 추가하고 번들/사용자/프로젝트 스킬을 함께 노출하도록 SkillService와 설정 UI를 확장했다. 슬래시 스킬 호출 시 인자 치환, 스킬 폴더 변수 치환, inline shell 실행, when_to_use 기반 자동 스킬 가이드를 실제 ChatWindow 런타임 경로에 연결했다. blanket deny 권한은 모델 노출 전 활성 도구 목록에서 먼저 제외하도록 AgentLoopService를 보강했고 관련 테스트와 README/DEVELOPMENT 문서를 업데이트했다. 검증: dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify_phase2\\ -p:IntermediateOutputPath=obj\\verify_phase2\\ (경고 0 / 오류 0) 검증: dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj -c Release -v minimal --filter "AgentToolCatalogTests|SkillServiceRuntimePolicyTests" -p:OutputPath=bin\\verify_phase2_tests\\ -p:IntermediateOutputPath=obj\\verify_phase2_tests\\ (통과 16, 기존 WorkspaceContextGeneratorTests nullable 경고 1건 유지)
This commit is contained in:
@@ -40,7 +40,7 @@ public partial class AgentSettingsWindow : Window
|
||||
private void LoadFromSettings()
|
||||
{
|
||||
SkillService.EnsureSkillFolder();
|
||||
SkillService.LoadSkills(_llm.SkillsFolderPath);
|
||||
SkillService.LoadSkills(_llm.SkillsFolderPath, ResolveSkillProjectRoot());
|
||||
|
||||
_selectedService = (_llm.Service ?? "ollama").Trim().ToLowerInvariant();
|
||||
_selectedTheme = (_llm.AgentTheme ?? "system").Trim().ToLowerInvariant();
|
||||
@@ -564,12 +564,30 @@ public partial class AgentSettingsWindow : Window
|
||||
_settings.Settings.AiEnabled = true;
|
||||
_settings.Settings.OperationMode = OperationModePolicy.Normalize(_operationMode);
|
||||
_settings.Save();
|
||||
SkillService.LoadSkills(_llm.SkillsFolderPath);
|
||||
SkillService.LoadSkills(_llm.SkillsFolderPath, ResolveSkillProjectRoot());
|
||||
BuildSkillListPanel();
|
||||
DialogResult = true;
|
||||
Close();
|
||||
}
|
||||
|
||||
private string? ResolveSkillProjectRoot()
|
||||
{
|
||||
var candidates = new[]
|
||||
{
|
||||
_llm.CodeWorkFolder,
|
||||
_llm.CoworkWorkFolder,
|
||||
_llm.WorkFolder
|
||||
};
|
||||
|
||||
foreach (var candidate in candidates)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(candidate) && System.IO.Directory.Exists(candidate))
|
||||
return candidate.Trim();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void BtnBrowseSkillFolder_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var dlg = new System.Windows.Forms.FolderBrowserDialog
|
||||
@@ -611,7 +629,7 @@ public partial class AgentSettingsWindow : Window
|
||||
Padding = new Thickness(12, 10, 12, 10),
|
||||
Child = new TextBlock
|
||||
{
|
||||
Text = "로드된 스킬이 없습니다. 스킬 폴더를 열어 `.skill.md` 또는 `SKILL.md` 파일을 추가한 뒤 저장하면 다시 불러옵니다.",
|
||||
Text = "로드된 스킬이 없습니다. 기본/추가 스킬 폴더 또는 프로젝트 `.claude/skills` 아래에 `.skill.md`나 `SKILL.md`를 추가한 뒤 저장하면 다시 불러옵니다.",
|
||||
FontSize = 11,
|
||||
TextWrapping = TextWrapping.Wrap,
|
||||
Foreground = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray,
|
||||
@@ -622,8 +640,10 @@ public partial class AgentSettingsWindow : Window
|
||||
|
||||
var groups = new[]
|
||||
{
|
||||
new { Title = "내장 스킬", Items = skills.Where(s => string.IsNullOrWhiteSpace(s.Requires)).ToList() },
|
||||
new { Title = "고급 스킬", Items = skills.Where(s => !string.IsNullOrWhiteSpace(s.Requires)).ToList() },
|
||||
new { Title = "번들 스킬", Items = skills.Where(s => string.Equals(s.SourceScope, "bundled", StringComparison.OrdinalIgnoreCase)).ToList() },
|
||||
new { Title = "프로젝트 스킬", Items = skills.Where(s => string.Equals(s.SourceScope, "project", StringComparison.OrdinalIgnoreCase)).ToList() },
|
||||
new { Title = "사용자/추가 스킬", Items = skills.Where(s => !string.Equals(s.SourceScope, "bundled", StringComparison.OrdinalIgnoreCase) && !string.Equals(s.SourceScope, "project", StringComparison.OrdinalIgnoreCase) && string.IsNullOrWhiteSpace(s.Requires)).ToList() },
|
||||
new { Title = "고급 스킬", Items = skills.Where(s => !string.IsNullOrWhiteSpace(s.Requires) && !string.Equals(s.SourceScope, "project", StringComparison.OrdinalIgnoreCase)).ToList() },
|
||||
};
|
||||
|
||||
foreach (var group in groups)
|
||||
|
||||
Reference in New Issue
Block a user