탭별 설정 해석기를 도입해 Cowork/Code 분기 동작을 단일화
Some checks failed
Release Gate / gate (push) Has been cancelled
Some checks failed
Release Gate / gate (push) Has been cancelled
- AgentTabSettingsResolver 신규 추가: 탭 판별, post-tool 검증 활성 여부, Code 전용 비활성 도구 목록 계산 - AgentLoopService.MergeDisabledTools에서 Code 전용 도구 비활성 계산을 resolver 경로로 전환 - AgentLoopTransitions.Execution에서 post-tool verification 판단 시 resolver 결과를 사용하도록 정리 - AgentTabSettingsResolverTests 신규 추가(탭 판별/검증 플래그 분기/비활성 도구 계산) - README.md 업데이트 시각(2026-04-04 13:32 KST) 및 변경 이력 항목 갱신 - docs/DEVELOPMENT.md 연속 실행 28차 이력 추가 - 검증: dotnet build(use shared compilation off) 경고 0/오류 0, 필터 테스트 49건 통과
This commit is contained in:
@@ -222,7 +222,7 @@ public class MyHandler : IActionHandler
|
|||||||
|
|
||||||
### v0.7.3 — AX Agent 권한 코어 재구성 + 입력 계층 정리
|
### v0.7.3 — AX Agent 권한 코어 재구성 + 입력 계층 정리
|
||||||
|
|
||||||
업데이트: 2026-04-04 13:25 (KST)
|
업데이트: 2026-04-04 13:32 (KST)
|
||||||
|
|
||||||
| 분류 | 내용 |
|
| 분류 | 내용 |
|
||||||
|------|------|
|
|------|------|
|
||||||
@@ -278,6 +278,7 @@ public class MyHandler : IActionHandler
|
|||||||
| slash 명령 카탈로그 분리 | `ChatWindow` 내부 대형 slash 사전을 `SlashCommandCatalog`로 분리해 입력 계층 결합도를 낮추고 유지보수 범위를 축소 |
|
| slash 명령 카탈로그 분리 | `ChatWindow` 내부 대형 slash 사전을 `SlashCommandCatalog`로 분리해 입력 계층 결합도를 낮추고 유지보수 범위를 축소 |
|
||||||
| slash 조회 API 전환 | 내장 slash 매칭/조회 경로를 `SlashCommandCatalog.MatchBuiltinCommands`/`TryGetEntry`로 통일 |
|
| slash 조회 API 전환 | 내장 slash 매칭/조회 경로를 `SlashCommandCatalog.MatchBuiltinCommands`/`TryGetEntry`로 통일 |
|
||||||
| 권한 표시 카탈로그 분리 | 권한 모드 라벨/설명/아이콘/색을 `PermissionModePresentationCatalog`로 분리해 팝업 표면 기준을 단일화 |
|
| 권한 표시 카탈로그 분리 | 권한 모드 라벨/설명/아이콘/색을 `PermissionModePresentationCatalog`로 분리해 팝업 표면 기준을 단일화 |
|
||||||
|
| 탭별 설정 해석기 도입 | `AgentTabSettingsResolver`를 추가해 Cowork/Code 분기(검증 활성/Code 전용 도구 비활성)를 단일 경로로 정리 |
|
||||||
| Slash palette 상태 분리 시작 | `ChatWindow`에 몰려 있던 slash 상태를 `SlashPaletteState`로 분리해 이후 Codex/Claude형 composer 개편 기반 마련 |
|
| Slash palette 상태 분리 시작 | `ChatWindow`에 몰려 있던 slash 상태를 `SlashPaletteState`로 분리해 이후 Codex/Claude형 composer 개편 기반 마련 |
|
||||||
| 런처 이미지 미리보기 추가 | `#` 클립보드 이미지 항목에서 `Shift+Enter`로 전용 미리보기 창을 열고, 줌·원본 해상도 확인·PNG/JPEG/BMP 저장·클립보드 복사를 지원 |
|
| 런처 이미지 미리보기 추가 | `#` 클립보드 이미지 항목에서 `Shift+Enter`로 전용 미리보기 창을 열고, 줌·원본 해상도 확인·PNG/JPEG/BMP 저장·클립보드 복사를 지원 |
|
||||||
| 검증 | `dotnet build` 경고 0 / 오류 0, `dotnet test` 436 passed / 0 failed |
|
| 검증 | `dotnet build` 경고 0 / 오류 0, `dotnet test` 436 passed / 0 failed |
|
||||||
|
|||||||
@@ -3343,3 +3343,27 @@ else:
|
|||||||
### 3) 품질 게이트
|
### 3) 품질 게이트
|
||||||
- dotnet build src/AxCopilot/AxCopilot.csproj 통과 (경고 0, 오류 0).
|
- dotnet build src/AxCopilot/AxCopilot.csproj 통과 (경고 0, 오류 0).
|
||||||
- dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj --no-build --filter "FullyQualifiedName~ChatWindowSlashPolicyTests|FullyQualifiedName~OperationModeReadinessTests" 통과 (43 passed, 0 failed).
|
- dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj --no-build --filter "FullyQualifiedName~ChatWindowSlashPolicyTests|FullyQualifiedName~OperationModeReadinessTests" 통과 (43 passed, 0 failed).
|
||||||
|
## 2026-04-04 추가 진행 기록 (연속 실행 28차: 탭별 설정 해석기 도입)
|
||||||
|
|
||||||
|
업데이트: 2026-04-04 13:32 (KST)
|
||||||
|
|
||||||
|
### 1) 탭별 설정 해석 단일화
|
||||||
|
- 신규 파일 AgentTabSettingsResolver 추가.
|
||||||
|
- ActiveTab 기준 공통 분기 제공:
|
||||||
|
- IsCodeTab, IsCoworkTab
|
||||||
|
- IsPostToolVerificationEnabled(activeTab, llm)
|
||||||
|
- EnumerateCodeTabDisabledTools(codeSettings)
|
||||||
|
|
||||||
|
### 2) Agent loop 연동
|
||||||
|
- AgentLoopService.MergeDisabledTools()에서 Code 탭 전용 도구 비활성 목록을 resolver로 계산하도록 전환.
|
||||||
|
- AgentLoopTransitions.Execution의 post-tool verification 판단에서 resolver 결과를 사용하도록 정리.
|
||||||
|
|
||||||
|
### 3) 테스트 보강
|
||||||
|
- AgentTabSettingsResolverTests 신규 추가:
|
||||||
|
- 탭 판별
|
||||||
|
- Cowork/Code 검증 플래그 분기
|
||||||
|
- Code 전용 비활성 도구 목록 계산
|
||||||
|
|
||||||
|
### 4) 품질 게이트
|
||||||
|
- dotnet build src/AxCopilot/AxCopilot.csproj -p:UseSharedCompilation=false -nodeReuse:false 통과 (경고 0, 오류 0).
|
||||||
|
- dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj --filter "FullyQualifiedName~AgentTabSettingsResolverTests|FullyQualifiedName~ChatWindowSlashPolicyTests|FullyQualifiedName~OperationModeReadinessTests" 통과 (49 passed, 0 failed).
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
using AxCopilot.Models;
|
||||||
|
using AxCopilot.Services.Agent;
|
||||||
|
using FluentAssertions;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace AxCopilot.Tests.Services;
|
||||||
|
|
||||||
|
public class AgentTabSettingsResolverTests
|
||||||
|
{
|
||||||
|
[Theory]
|
||||||
|
[InlineData("Code", true, false)]
|
||||||
|
[InlineData("Cowork", false, true)]
|
||||||
|
[InlineData("Chat", false, false)]
|
||||||
|
[InlineData(null, false, false)]
|
||||||
|
public void TabDetection_ShouldMatchExpected(string? tab, bool isCode, bool isCowork)
|
||||||
|
{
|
||||||
|
AgentTabSettingsResolver.IsCodeTab(tab).Should().Be(isCode);
|
||||||
|
AgentTabSettingsResolver.IsCoworkTab(tab).Should().Be(isCowork);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void IsPostToolVerificationEnabled_ShouldUseTabSpecificFlags()
|
||||||
|
{
|
||||||
|
var llm = new LlmSettings
|
||||||
|
{
|
||||||
|
EnableCoworkVerification = true,
|
||||||
|
Code = new CodeSettings
|
||||||
|
{
|
||||||
|
EnableCodeVerification = false,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
AgentTabSettingsResolver.IsPostToolVerificationEnabled("Cowork", llm).Should().BeTrue();
|
||||||
|
AgentTabSettingsResolver.IsPostToolVerificationEnabled("Code", llm).Should().BeFalse();
|
||||||
|
AgentTabSettingsResolver.IsPostToolVerificationEnabled("Chat", llm).Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void EnumerateCodeTabDisabledTools_ShouldReflectCodeSettings()
|
||||||
|
{
|
||||||
|
var code = new CodeSettings
|
||||||
|
{
|
||||||
|
EnablePlanModeTools = false,
|
||||||
|
EnableWorktreeTools = true,
|
||||||
|
EnableTeamTools = false,
|
||||||
|
EnableCronTools = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
var disabled = AgentTabSettingsResolver.EnumerateCodeTabDisabledTools(code).ToList();
|
||||||
|
|
||||||
|
disabled.Should().Contain(["enter_plan_mode", "exit_plan_mode"]);
|
||||||
|
disabled.Should().Contain(["team_create", "team_delete"]);
|
||||||
|
disabled.Should().Contain(["cron_create", "cron_delete", "cron_list"]);
|
||||||
|
disabled.Should().NotContain(["enter_worktree", "exit_worktree"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1589,33 +1589,13 @@ public partial class AgentLoopService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.Equals(ActiveTab, "Code", StringComparison.OrdinalIgnoreCase))
|
if (!AgentTabSettingsResolver.IsCodeTab(ActiveTab))
|
||||||
return disabled;
|
return disabled;
|
||||||
|
|
||||||
var code = _settings.Settings.Llm.Code;
|
var code = _settings.Settings.Llm.Code;
|
||||||
if (!code.EnablePlanModeTools)
|
foreach (var toolName in AgentTabSettingsResolver.EnumerateCodeTabDisabledTools(code))
|
||||||
{
|
{
|
||||||
disabled.Add("enter_plan_mode");
|
disabled.Add(toolName);
|
||||||
disabled.Add("exit_plan_mode");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!code.EnableWorktreeTools)
|
|
||||||
{
|
|
||||||
disabled.Add("enter_worktree");
|
|
||||||
disabled.Add("exit_worktree");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!code.EnableTeamTools)
|
|
||||||
{
|
|
||||||
disabled.Add("team_create");
|
|
||||||
disabled.Add("team_delete");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!code.EnableCronTools)
|
|
||||||
{
|
|
||||||
disabled.Add("cron_create");
|
|
||||||
disabled.Add("cron_delete");
|
|
||||||
disabled.Add("cron_list");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return disabled;
|
return disabled;
|
||||||
|
|||||||
@@ -1399,12 +1399,13 @@ public partial class AgentLoopService
|
|||||||
if (!result.Success || !IsTerminalDocumentTool(call.ToolName) || toolCalls.Count != 1)
|
if (!result.Success || !IsTerminalDocumentTool(call.ToolName) || toolCalls.Count != 1)
|
||||||
return (false, false);
|
return (false, false);
|
||||||
|
|
||||||
|
var verificationEnabled = AgentTabSettingsResolver.IsPostToolVerificationEnabled(ActiveTab, llm);
|
||||||
var shouldVerify = ShouldRunPostToolVerification(
|
var shouldVerify = ShouldRunPostToolVerification(
|
||||||
ActiveTab,
|
ActiveTab,
|
||||||
call.ToolName,
|
call.ToolName,
|
||||||
result.Success,
|
result.Success,
|
||||||
llm.Code.EnableCodeVerification,
|
verificationEnabled,
|
||||||
llm.EnableCoworkVerification);
|
verificationEnabled);
|
||||||
var consumedExtraIteration = false;
|
var consumedExtraIteration = false;
|
||||||
if (shouldVerify)
|
if (shouldVerify)
|
||||||
{
|
{
|
||||||
@@ -1427,12 +1428,13 @@ public partial class AgentLoopService
|
|||||||
if (!result.Success)
|
if (!result.Success)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
var verificationEnabled = AgentTabSettingsResolver.IsPostToolVerificationEnabled(ActiveTab, llm);
|
||||||
var shouldVerify = ShouldRunPostToolVerification(
|
var shouldVerify = ShouldRunPostToolVerification(
|
||||||
ActiveTab,
|
ActiveTab,
|
||||||
call.ToolName,
|
call.ToolName,
|
||||||
result.Success,
|
result.Success,
|
||||||
llm.Code.EnableCodeVerification,
|
verificationEnabled,
|
||||||
llm.EnableCoworkVerification);
|
verificationEnabled);
|
||||||
if (!shouldVerify)
|
if (!shouldVerify)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|||||||
49
src/AxCopilot/Services/Agent/AgentTabSettingsResolver.cs
Normal file
49
src/AxCopilot/Services/Agent/AgentTabSettingsResolver.cs
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
using AxCopilot.Models;
|
||||||
|
|
||||||
|
namespace AxCopilot.Services.Agent;
|
||||||
|
|
||||||
|
internal static class AgentTabSettingsResolver
|
||||||
|
{
|
||||||
|
public static bool IsCodeTab(string? activeTab)
|
||||||
|
=> string.Equals(activeTab, "Code", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
public static bool IsCoworkTab(string? activeTab)
|
||||||
|
=> string.Equals(activeTab, "Cowork", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
public static bool IsPostToolVerificationEnabled(string? activeTab, LlmSettings llm)
|
||||||
|
{
|
||||||
|
if (IsCodeTab(activeTab))
|
||||||
|
return llm.Code.EnableCodeVerification;
|
||||||
|
if (IsCoworkTab(activeTab))
|
||||||
|
return llm.EnableCoworkVerification;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<string> EnumerateCodeTabDisabledTools(CodeSettings code)
|
||||||
|
{
|
||||||
|
if (!code.EnablePlanModeTools)
|
||||||
|
{
|
||||||
|
yield return "enter_plan_mode";
|
||||||
|
yield return "exit_plan_mode";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!code.EnableWorktreeTools)
|
||||||
|
{
|
||||||
|
yield return "enter_worktree";
|
||||||
|
yield return "exit_worktree";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!code.EnableTeamTools)
|
||||||
|
{
|
||||||
|
yield return "team_create";
|
||||||
|
yield return "team_delete";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!code.EnableCronTools)
|
||||||
|
{
|
||||||
|
yield return "cron_create";
|
||||||
|
yield return "cron_delete";
|
||||||
|
yield return "cron_list";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user