AX Agent 도구·스킬 정합성 재구성 및 실행 품질 보강
변경 목적: - AX Agent의 도구 이름, 내부 설정, 스킬 정책, 실행 루프 사이의 불일치를 줄이고 전체 동작 품질을 높인다. - claw-code 수준의 일관된 동작 품질을 참고하되 AX 구조에 맞는 고유한 카탈로그·정규화 레이어로 재구성한다. 핵심 수정사항: - 도구 canonical id, legacy alias, 탭 노출, 설정 카테고리, read-only 분류를 중앙 카탈로그로 통합했다. - ToolRegistry, AgentLoopService, 병렬 실행 분류, 권한 처리, 훅 처리, 스킬 allowed-tools 해석이 같은 이름 체계를 사용하도록 정리했다. - Agent 설정/일반 설정/도움말의 도구 카드와 훅 편집기, 스킬 설명을 현재 런타임 구조에 맞게 갱신했다. - 컨텍스트 압축, intent gate, spawn agents, session learning, model prompt adapter, workspace context 관련 변경과 테스트 추가를 함께 반영했다. - 문서 이력과 비교/로드맵 문서를 최신 상태로 갱신했다. 검증 결과: - dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\verify_toolcat\ -p:IntermediateOutputPath=obj\verify_toolcat\ : 경고 0 / 오류 0 - dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj -c Release -v minimal --filter AgentToolCatalogTests -p:OutputPath=bin\verify_toolcat_tests\ -p:IntermediateOutputPath=obj\verify_toolcat_tests\ : 통과 8
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using System.Windows;
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
@@ -59,6 +60,7 @@ public partial class AgentSettingsWindow : Window
|
||||
TxtContextCompactTriggerPercent.Text = Math.Clamp(_llm.ContextCompactTriggerPercent, 10, 95).ToString();
|
||||
TxtMaxContextTokens.Text = Math.Max(1024, _llm.MaxContextTokens).ToString();
|
||||
TxtMaxRetryOnError.Text = Math.Clamp(_llm.MaxRetryOnError, 0, 10).ToString();
|
||||
ChkEnableIbmDiagnosticLog.IsChecked = _llm.EnableIbmDiagnosticLog;
|
||||
|
||||
ChkEnableSkillSystem.IsChecked = _llm.EnableSkillSystem;
|
||||
ChkEnableToolHooks.IsChecked = _llm.EnableToolHooks;
|
||||
@@ -77,7 +79,8 @@ public partial class AgentSettingsWindow : Window
|
||||
TxtSlashPopupPageSize.Text = Math.Clamp(_llm.SlashPopupPageSize, 3, 20).ToString();
|
||||
ChkEnableDragDropAiActions.IsChecked = _llm.EnableDragDropAiActions;
|
||||
ChkDragDropAutoSend.IsChecked = _llm.DragDropAutoSend;
|
||||
_disabledTools = new HashSet<string>(_llm.DisabledTools ?? new(), StringComparer.OrdinalIgnoreCase);
|
||||
_disabledTools = new HashSet<string>(AgentToolCatalog.CanonicalizeMany(_llm.DisabledTools ?? new()), StringComparer.OrdinalIgnoreCase);
|
||||
_llm.AgentHooks = AgentToolCatalog.CanonicalizeHooks(_llm.AgentHooks);
|
||||
|
||||
RefreshServiceCards();
|
||||
RefreshThemeCards();
|
||||
@@ -141,13 +144,27 @@ public partial class AgentSettingsWindow : Window
|
||||
private void ShowPanel(string panel)
|
||||
{
|
||||
_activePanel = panel;
|
||||
PanelBasic.Visibility = panel == "basic" ? Visibility.Visible : Visibility.Collapsed;
|
||||
PanelChat.Visibility = panel == "chat" ? Visibility.Visible : Visibility.Collapsed;
|
||||
PanelCowork.Visibility = panel == "cowork" ? Visibility.Visible : Visibility.Collapsed;
|
||||
PanelCode.Visibility = panel == "code" ? Visibility.Visible : Visibility.Collapsed;
|
||||
PanelDev.Visibility = panel == "dev" ? Visibility.Visible : Visibility.Collapsed;
|
||||
PanelTools.Visibility = panel == "tools" ? Visibility.Visible : Visibility.Collapsed;
|
||||
PanelEtc.Visibility = panel == "etc" ? Visibility.Visible : Visibility.Collapsed;
|
||||
var panels = new (FrameworkElement Element, string Key)[]
|
||||
{
|
||||
(PanelBasic, "basic"), (PanelChat, "chat"), (PanelCowork, "cowork"),
|
||||
(PanelCode, "code"), (PanelDev, "dev"), (PanelTools, "tools"), (PanelEtc, "etc")
|
||||
};
|
||||
foreach (var (element, key) in panels)
|
||||
{
|
||||
if (key == panel)
|
||||
{
|
||||
element.Opacity = 0;
|
||||
element.Visibility = Visibility.Visible;
|
||||
element.BeginAnimation(UIElement.OpacityProperty,
|
||||
new System.Windows.Media.Animation.DoubleAnimation(0, 1, TimeSpan.FromMilliseconds(150))
|
||||
{ EasingFunction = new System.Windows.Media.Animation.QuadraticEase() });
|
||||
}
|
||||
else
|
||||
{
|
||||
element.BeginAnimation(UIElement.OpacityProperty, null);
|
||||
element.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
RefreshTabCards();
|
||||
if (panel == "tools")
|
||||
LoadToolCards();
|
||||
@@ -520,6 +537,7 @@ public partial class AgentSettingsWindow : Window
|
||||
_llm.ContextCompactTriggerPercent = ParseInt(TxtContextCompactTriggerPercent.Text, 80, 10, 95);
|
||||
_llm.MaxContextTokens = ParseInt(TxtMaxContextTokens.Text, 4096, 1024, 200000);
|
||||
_llm.MaxRetryOnError = ParseInt(TxtMaxRetryOnError.Text, 3, 0, 10);
|
||||
_llm.EnableIbmDiagnosticLog = ChkEnableIbmDiagnosticLog.IsChecked == true;
|
||||
|
||||
_llm.EnableSkillSystem = ChkEnableSkillSystem.IsChecked == true;
|
||||
_llm.EnableToolHooks = ChkEnableToolHooks.IsChecked == true;
|
||||
@@ -538,7 +556,10 @@ public partial class AgentSettingsWindow : Window
|
||||
_llm.SlashPopupPageSize = ParseInt(TxtSlashPopupPageSize.Text, 7, 3, 20);
|
||||
_llm.EnableDragDropAiActions = ChkEnableDragDropAiActions.IsChecked == true;
|
||||
_llm.DragDropAutoSend = ChkDragDropAutoSend.IsChecked == true;
|
||||
_llm.DisabledTools = _disabledTools.OrderBy(x => x, StringComparer.OrdinalIgnoreCase).ToList();
|
||||
_llm.DisabledTools = AgentToolCatalog.CanonicalizeMany(_disabledTools)
|
||||
.OrderBy(x => x, StringComparer.OrdinalIgnoreCase)
|
||||
.ToList();
|
||||
_llm.AgentHooks = AgentToolCatalog.CanonicalizeHooks(_llm.AgentHooks);
|
||||
|
||||
_settings.Settings.AiEnabled = true;
|
||||
_settings.Settings.OperationMode = OperationModePolicy.Normalize(_operationMode);
|
||||
@@ -705,24 +726,13 @@ public partial class AgentSettingsWindow : Window
|
||||
_toolCardsLoaded = true;
|
||||
|
||||
using var tools = ToolRegistry.CreateDefault();
|
||||
var categories = new Dictionary<string, List<IAgentTool>>
|
||||
{
|
||||
["파일/검색"] = new(),
|
||||
["문서/리뷰"] = new(),
|
||||
["코드/개발"] = new(),
|
||||
["시스템/유틸"] = new(),
|
||||
};
|
||||
var toolCategoryMap = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
["file_read"] = "파일/검색", ["file_write"] = "파일/검색", ["file_edit"] = "파일/검색", ["glob"] = "파일/검색", ["grep"] = "파일/검색",
|
||||
["document_review"] = "문서/리뷰", ["format_convert"] = "문서/리뷰", ["template_render"] = "문서/리뷰", ["text_summarize"] = "문서/리뷰",
|
||||
["build_run"] = "코드/개발", ["git_tool"] = "코드/개발", ["lsp"] = "코드/개발", ["code_review"] = "코드/개발", ["test_loop"] = "코드/개발",
|
||||
["process"] = "시스템/유틸", ["notify"] = "시스템/유틸", ["clipboard"] = "시스템/유틸", ["env"] = "시스템/유틸", ["skill_manager"] = "시스템/유틸",
|
||||
};
|
||||
var categories = new Dictionary<string, List<IAgentTool>>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
foreach (var tool in tools.All)
|
||||
{
|
||||
var category = toolCategoryMap.TryGetValue(tool.Name, out var mapped) ? mapped : "시스템/유틸";
|
||||
var category = AgentToolCatalog.GetMetadata(tool.Name).SettingsCategory;
|
||||
if (!categories.ContainsKey(category))
|
||||
categories[category] = new List<IAgentTool>();
|
||||
categories[category].Add(tool);
|
||||
}
|
||||
|
||||
@@ -866,7 +876,7 @@ public partial class AgentSettingsWindow : Window
|
||||
}
|
||||
|
||||
var nameBox = AddField("이름", existing?.Name ?? "");
|
||||
var toolBox = AddField("대상 도구 (* = 전체)", existing?.ToolName ?? "*");
|
||||
var toolBox = AddField("대상 도구 (* = 전체)", AgentToolCatalog.CanonicalizeHookTarget(existing?.ToolName ?? "*"));
|
||||
var pathBox = AddField("스크립트 경로", existing?.ScriptPath ?? "");
|
||||
var argsBox = AddField("인수", existing?.Arguments ?? "");
|
||||
|
||||
@@ -886,7 +896,7 @@ public partial class AgentSettingsWindow : Window
|
||||
var entry = new AgentHookEntry
|
||||
{
|
||||
Name = nameBox.Text.Trim(),
|
||||
ToolName = string.IsNullOrWhiteSpace(toolBox.Text) ? "*" : toolBox.Text.Trim(),
|
||||
ToolName = AgentToolCatalog.CanonicalizeHookTarget(toolBox.Text),
|
||||
Timing = pre.IsChecked == true ? "pre" : "post",
|
||||
ScriptPath = pathBox.Text.Trim(),
|
||||
Arguments = argsBox.Text.Trim(),
|
||||
|
||||
Reference in New Issue
Block a user