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:
@@ -158,11 +158,27 @@ public sealed class ChatSessionStateService
|
||||
var normalizedTab = NormalizeTab(tab);
|
||||
var created = new ChatConversation { Tab = normalizedTab };
|
||||
|
||||
// Code/Cowork 탭: 매 대화마다 폴더를 새로 선택하도록 빈 상태로 시작
|
||||
// ── 버그 수정: 현재 사용자가 선택한 권한(FilePermission)을 새 대화에 승계 ──
|
||||
// 이전 버그: Permission=null인 상태로 생성되면 LoadConversationSettings가
|
||||
// DefaultAgentPermission(별도 필드, 기본 "Deny")으로 폴백하고
|
||||
// _settings.Llm.FilePermission을 덮어써버림.
|
||||
// → UI엔 "권한 건너뛰기"가 표시돼도 실제 실행 시엔 Default/Deny 모드라
|
||||
// html_create/document_plan 등에서 승인 창이 뜸.
|
||||
// Chat 탭은 기본 Deny가 안전하므로 승계하지 않음 (기존 동작 유지).
|
||||
if (string.Equals(normalizedTab, "Code", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(normalizedTab, "Cowork", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
created.WorkFolder = "";
|
||||
try
|
||||
{
|
||||
var currentPerm = AxCopilot.Services.Agent.PermissionModeCatalog.NormalizeGlobalMode(
|
||||
settings.Settings.Llm.FilePermission);
|
||||
// Deny는 새 대화의 기본으로는 부적절(사용자가 의도적으로 Deny를 선택했을 가능성도 있지만
|
||||
// Cowork/Code에서는 에이전트 실행 자체가 주 목적이므로 그대로 두면 혼란).
|
||||
// 단, 단순 승계가 사용자 의도에 가장 부합하므로 그대로 반영.
|
||||
created.Permission = currentPerm;
|
||||
}
|
||||
catch { /* 설정 접근 실패 시 Permission=null 유지 (fallback 경로) */ }
|
||||
CurrentConversation = created;
|
||||
return created;
|
||||
}
|
||||
@@ -271,13 +287,20 @@ public sealed class ChatSessionStateService
|
||||
{
|
||||
var normalizedTab = NormalizeTab(tab);
|
||||
conversation.Tab = normalizedTab;
|
||||
NormalizeLoadedConversation(conversation);
|
||||
var normalized = NormalizeLoadedConversation(conversation);
|
||||
|
||||
CurrentConversation = conversation;
|
||||
if (remember && !string.IsNullOrWhiteSpace(conversation.Id))
|
||||
RememberConversation(normalizedTab, conversation.Id);
|
||||
|
||||
try { storage?.Save(conversation); } catch { }
|
||||
// 대화 "선택"만으로는 대화 내용이 변하지 않음. 기존에는 무조건 Save()를 호출해
|
||||
// storage.Save()가 UpdatedAt = DateTime.Now로 갱신 → 목록에서 맨 위로 올라가는 부작용.
|
||||
// 실제 정규화(NormalizeLoadedConversation)가 일어난 경우에만 저장한다.
|
||||
// — 다른 경로(EnsureCurrentConversation 등)도 이미 if(normalized) 패턴을 따른다.
|
||||
if (normalized)
|
||||
{
|
||||
try { storage?.Save(conversation); } catch { }
|
||||
}
|
||||
return conversation;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user