diff --git a/README.md b/README.md index 6579137..a8b7d52 100644 --- a/README.md +++ b/README.md @@ -2063,3 +2063,10 @@ MIT License - 검증: - `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify_empty_workspace_fix2\\ -p:IntermediateOutputPath=obj\\verify_empty_workspace_fix2\\` 경고 0 / 오류 0 - `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj -c Release -v minimal --filter "FullyQualifiedName~RunAsync_EmptyWorkspace_BlocksExternalFallbackAndRecoversToFileWrite|FullyQualifiedName~RunAsync_EmptyWorkspace_DisallowsSkillManagerAndRecoversToFileWrite|FullyQualifiedName~RunAsync_TextEmbeddedToolCall_RecoversAndExecutesFileWrite|FullyQualifiedName~Classify_ShouldRecoverToolCallEmbeddedInText" -p:OutputPath=bin\\verify_empty_workspace_fix2_tests\\ -p:IntermediateOutputPath=obj\\verify_empty_workspace_fix2_tests\\` 통과 4 + +업데이트: 2026-04-15 14:18 (KST) +- broader AgentLoop E2E 정합성을 맞췄습니다. [AgentLoopE2ETests.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot.Tests/Services/AgentLoopE2ETests.cs)에서 `math_eval`과 hook 기반 계산 시나리오는 실제 도구 카탈로그 정책에 맞춰 `Chat` 대신 `Cowork` 탭 기준으로 실행되도록 정리했습니다. 현재 [AgentToolCatalog.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Services/Agent/AgentToolCatalog.cs) 기준 `math_eval`은 `Cowork,Code` 도구입니다. +- [AgentLoopService.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Services/Agent/AgentLoopService.cs)의 `activeTools.Count == 0` 처리도 개선했습니다. 실제 `allowed-tools` 런타임 정책이 있을 때만 스킬 정책 오류 문구를 반환하고, 그 외에는 현재 탭에 사용 가능한 도구가 없다는 탭 기준 메시지를 반환하도록 분기해 잘못된 원인 안내를 줄였습니다. +- 검증: + - `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify_runtime_policy_alignment_build\\ -p:IntermediateOutputPath=obj\\verify_runtime_policy_alignment_build\\` 경고 0 / 오류 0 + - `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj -c Release -v minimal --filter "AgentLoopE2ETests|AgentLoopResponseClassificationServiceTests" -p:OutputPath=bin\\verify_runtime_policy_alignment\\ -p:IntermediateOutputPath=obj\\verify_runtime_policy_alignment\\` 통과 19 diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index 82b6cd3..eff3767 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -1336,3 +1336,24 @@ UI ?붿옄???€洹쒕え 由ы뙥?좊쭅 ???꾪뿕 ?묒뾽 ??湲곕줉???덉쟾 ### 검증 - `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify_empty_workspace_fix2\\ -p:IntermediateOutputPath=obj\\verify_empty_workspace_fix2\\` 경고 0 / 오류 0 - `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj -c Release -v minimal --filter "FullyQualifiedName~RunAsync_EmptyWorkspace_BlocksExternalFallbackAndRecoversToFileWrite|FullyQualifiedName~RunAsync_EmptyWorkspace_DisallowsSkillManagerAndRecoversToFileWrite|FullyQualifiedName~RunAsync_TextEmbeddedToolCall_RecoversAndExecutesFileWrite|FullyQualifiedName~Classify_ShouldRecoverToolCallEmbeddedInText" -p:OutputPath=bin\\verify_empty_workspace_fix2_tests\\ -p:IntermediateOutputPath=obj\\verify_empty_workspace_fix2_tests\\` 통과 4 + +업데이트: 2026-04-15 14:18 (KST) + +### AgentLoop 탭 정책 / broader E2E 정합성 수정 +- `AgentLoopE2ETests.cs` + - `RunAsync_ExecutesToolCall_AndCompletesWithFinalText()` + - `RunAsync_UnknownTool_RecoversAndCompletes()` + - `RunAsync_PlanModeAlways_EmitsPlanningThenExecutesTool()` + - `RunAsync_PreHookInputMutation_ChangesToolArguments()` + - 위 4개 시나리오의 `ActiveTab`을 `Chat`에서 `Cowork`로 정리했습니다. + - 근거: [AgentToolCatalog.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Services/Agent/AgentToolCatalog.cs) 기준 `math_eval`은 `Cowork,Code` 도구이며 Chat 기본 노출 대상이 아닙니다. 기존 broader E2E 실패는 런타임 정책 누수라기보다 테스트가 현행 탭 정책보다 오래된 가정을 유지한 영향이었습니다. + +### no-tool 상태 메시지 분기 보강 +- `AgentLoopService.cs` + - `activeTools.Count == 0`일 때의 오류 반환을 2갈래로 분리했습니다. + - 실제 `runtimeOverrides.AllowedToolNames`가 있을 때만 기존 `현재 스킬 정책에서 허용된 도구가 없어...` 문구를 유지합니다. + - 그 외에는 `현재 {탭} 탭에서 사용 가능한 도구가 없어...` 형식의 탭 기준 메시지를 반환해 원인 안내가 오해를 부르지 않도록 정리했습니다. + +### 검증 +- `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify_runtime_policy_alignment_build\\ -p:IntermediateOutputPath=obj\\verify_runtime_policy_alignment_build\\` 경고 0 / 오류 0 +- `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj -c Release -v minimal --filter "AgentLoopE2ETests|AgentLoopResponseClassificationServiceTests" -p:OutputPath=bin\\verify_runtime_policy_alignment\\ -p:IntermediateOutputPath=obj\\verify_runtime_policy_alignment\\` 통과 19 diff --git a/src/AxCopilot.Tests/Services/AgentLoopE2ETests.cs b/src/AxCopilot.Tests/Services/AgentLoopE2ETests.cs index 2d54faf..fbff93b 100644 --- a/src/AxCopilot.Tests/Services/AgentLoopE2ETests.cs +++ b/src/AxCopilot.Tests/Services/AgentLoopE2ETests.cs @@ -26,7 +26,7 @@ public class AgentLoopE2ETests var settings = BuildLoopSettings(server.Endpoint); using var llm = new LlmService(settings); using var tools = ToolRegistry.CreateDefault(); - var loop = new AgentLoopService(llm, tools, settings) { ActiveTab = "Chat" }; + var loop = new AgentLoopService(llm, tools, settings) { ActiveTab = "Cowork" }; var events = new List(); loop.EventOccurred += evt => events.Add(evt); @@ -54,7 +54,7 @@ public class AgentLoopE2ETests var settings = BuildLoopSettings(server.Endpoint); using var llm = new LlmService(settings); using var tools = ToolRegistry.CreateDefault(); - var loop = new AgentLoopService(llm, tools, settings) { ActiveTab = "Chat" }; + var loop = new AgentLoopService(llm, tools, settings) { ActiveTab = "Cowork" }; var events = new List(); loop.EventOccurred += evt => events.Add(evt); @@ -81,7 +81,7 @@ public class AgentLoopE2ETests var settings = BuildLoopSettings(server.Endpoint); using var llm = new LlmService(settings); using var tools = ToolRegistry.CreateDefault(); - var loop = new AgentLoopService(llm, tools, settings) { ActiveTab = "Chat" }; + var loop = new AgentLoopService(llm, tools, settings) { ActiveTab = "Cowork" }; var events = new List(); loop.EventOccurred += evt => events.Add(evt); @@ -167,7 +167,7 @@ public class AgentLoopE2ETests using var llm = new LlmService(settings); using var tools = ToolRegistry.CreateDefault(); - var loop = new AgentLoopService(llm, tools, settings) { ActiveTab = "Chat" }; + var loop = new AgentLoopService(llm, tools, settings) { ActiveTab = "Cowork" }; var events = new List(); loop.EventOccurred += evt => events.Add(evt); diff --git a/src/AxCopilot/Services/Agent/AgentLoopService.cs b/src/AxCopilot/Services/Agent/AgentLoopService.cs index 89a791e..8de6c4d 100644 --- a/src/AxCopilot/Services/Agent/AgentLoopService.cs +++ b/src/AxCopilot/Services/Agent/AgentLoopService.cs @@ -542,8 +542,15 @@ public partial class AgentLoopService var activeTools = cachedActiveTools; if (activeTools.Count == 0) { - EmitEvent(AgentEventType.Error, "", "현재 스킬 런타임 정책으로 사용 가능한 도구가 없습니다."); - return "⚠ 현재 스킬 정책에서 허용된 도구가 없어 작업을 진행할 수 없습니다. allowed-tools 설정을 확인하세요."; + if (runtimeOverrides != null && runtimeOverrides.AllowedToolNames.Count > 0) + { + EmitEvent(AgentEventType.Error, "", "현재 스킬 런타임 정책으로 사용 가능한 도구가 없습니다."); + return "⚠ 현재 스킬 정책에서 허용된 도구가 없어 작업을 진행할 수 없습니다. allowed-tools 설정을 확인하세요."; + } + + var tabLabel = string.IsNullOrWhiteSpace(ActiveTab) ? "현재" : ActiveTab; + EmitEvent(AgentEventType.Error, "", $"{tabLabel} 탭에서 사용 가능한 도구가 없습니다."); + return $"⚠ 현재 {tabLabel} 탭에서 사용 가능한 도구가 없어 작업을 진행할 수 없습니다. 탭별 도구 노출 정책을 확인하세요."; } var llmRequest = AgentLoopLlmRequestPreparationService.Prepare( queryMessages,