claw-code 동등 품질 4단계 연속 반영: Agentic 루프/상태복원/설정연동/릴리즈 게이트 정렬
Some checks failed
Release Gate / gate (push) Has been cancelled
Some checks failed
Release Gate / gate (push) Has been cancelled
- 도구 동등화: task/todo/tool-search + plan/worktree/team/cron 도구군 추가 및 ToolRegistry 등록\n- claw-code CamelCase 별칭 정규화 확장: EnterPlanMode/EnterWorktree/TeamCreate/CronCreate 등 -> 내부 snake_case 매핑\n- AgentLoop 런타임 강화: Code 탭 전용 도구 토글(CodeSettings) 반영, 비활성 도구 자동 차단\n- Worktree 상태 복원 연결: .ax/worktree_state.json 기반 루트 탐색/활성 worktree 복원 및 BuildContext 연동\n- 권한/플러그인 하드닝 기존 반영분 유지: target 기반 권한 판정 + internal 모드 플러그인 경로/manifest 검증\n- 설정 연동(UI): SettingsWindow Code 패널에 Plan/Worktree/Team/Cron 도구 on/off 토글 추가\n- 테스트 보강: AgentParityTools/AgentLoopE2E에 worktree 지속성, alias 정규화, 설정 차단 시나리오 추가\n- 검증 완료: dotnet build(경고0/오류0), ParityBenchmark 11/11, ReplayStability 12/12, 전체 371/371, release-gate 통과\n- 문서 동기화: AGENT_ROADMAP/NEXT_ROADMAP/CLAW_CODE_PARITY_PLAN 수치 및 기준 최신화
This commit is contained in:
@@ -1536,7 +1536,8 @@ public partial class AgentLoopService
|
||||
IEnumerable<string>? disabledToolNames,
|
||||
SkillRuntimeOverrides? runtimeOverrides)
|
||||
{
|
||||
var active = _tools.GetActiveTools(disabledToolNames);
|
||||
var mergedDisabled = MergeDisabledTools(disabledToolNames);
|
||||
var active = _tools.GetActiveTools(mergedDisabled);
|
||||
if (runtimeOverrides == null || runtimeOverrides.AllowedToolNames.Count == 0)
|
||||
return active;
|
||||
|
||||
@@ -1546,6 +1547,50 @@ public partial class AgentLoopService
|
||||
.AsReadOnly();
|
||||
}
|
||||
|
||||
private IEnumerable<string> MergeDisabledTools(IEnumerable<string>? disabledToolNames)
|
||||
{
|
||||
var disabled = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
if (disabledToolNames != null)
|
||||
{
|
||||
foreach (var name in disabledToolNames)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(name))
|
||||
disabled.Add(name);
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.Equals(ActiveTab, "Code", StringComparison.OrdinalIgnoreCase))
|
||||
return disabled;
|
||||
|
||||
var code = _settings.Settings.Llm.Code;
|
||||
if (!code.EnablePlanModeTools)
|
||||
{
|
||||
disabled.Add("enter_plan_mode");
|
||||
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;
|
||||
}
|
||||
|
||||
private static HashSet<string> ParseAllowedToolNames(string? raw)
|
||||
{
|
||||
var result = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
@@ -3510,6 +3555,25 @@ public partial class AgentLoopService
|
||||
["task"] = "spawn_agent",
|
||||
["sendmessage"] = "notify_tool",
|
||||
["powershell"] = "process",
|
||||
["toolsearch"] = "tool_search",
|
||||
["todowrite"] = "todo_write",
|
||||
["taskcreate"] = "task_create",
|
||||
["taskget"] = "task_get",
|
||||
["tasklist"] = "task_list",
|
||||
["taskupdate"] = "task_update",
|
||||
["taskstop"] = "task_stop",
|
||||
["taskoutput"] = "task_output",
|
||||
["enterplanmode"] = "enter_plan_mode",
|
||||
["exitplanmode"] = "exit_plan_mode",
|
||||
["enterworktree"] = "enter_worktree",
|
||||
["exitworktree"] = "exit_worktree",
|
||||
["teamcreate"] = "team_create",
|
||||
["teamdelete"] = "team_delete",
|
||||
["croncreate"] = "cron_create",
|
||||
["crondelete"] = "cron_delete",
|
||||
["cronlist"] = "cron_list",
|
||||
["config"] = "project_rules",
|
||||
["skill"] = "skill_manager",
|
||||
};
|
||||
|
||||
private static string ResolveRequestedToolName(string requestedToolName, IReadOnlyCollection<string> activeToolNames)
|
||||
@@ -3858,9 +3922,11 @@ public partial class AgentLoopService
|
||||
private AgentContext BuildContext()
|
||||
{
|
||||
var llm = _settings.Settings.Llm;
|
||||
var baseWorkFolder = llm.WorkFolder;
|
||||
var runtimeWorkFolder = ResolveRuntimeWorkFolder(baseWorkFolder);
|
||||
return new AgentContext
|
||||
{
|
||||
WorkFolder = llm.WorkFolder,
|
||||
WorkFolder = runtimeWorkFolder,
|
||||
Permission = llm.FilePermission,
|
||||
BlockedPaths = llm.BlockedPaths,
|
||||
BlockedExtensions = llm.BlockedExtensions,
|
||||
@@ -3875,6 +3941,34 @@ public partial class AgentLoopService
|
||||
};
|
||||
}
|
||||
|
||||
private static string ResolveRuntimeWorkFolder(string? configuredRoot)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(configuredRoot))
|
||||
return "";
|
||||
|
||||
try
|
||||
{
|
||||
var root = Path.GetFullPath(configuredRoot);
|
||||
if (!Directory.Exists(root))
|
||||
return root;
|
||||
|
||||
var state = WorktreeStateStore.Load(root);
|
||||
if (!string.IsNullOrWhiteSpace(state.Active))
|
||||
{
|
||||
var active = Path.GetFullPath(state.Active);
|
||||
if (Directory.Exists(active)
|
||||
&& active.StartsWith(root, StringComparison.OrdinalIgnoreCase))
|
||||
return active;
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return configuredRoot ?? "";
|
||||
}
|
||||
}
|
||||
|
||||
private static string DescribeToolTarget(string toolName, JsonElement input, AgentContext context)
|
||||
{
|
||||
static string? TryReadString(JsonElement inputElement, params string[] names)
|
||||
@@ -4049,7 +4143,7 @@ public partial class AgentLoopService
|
||||
runId = _currentRunId,
|
||||
tool = toolName,
|
||||
target,
|
||||
permission = context.GetEffectiveToolPermission(toolName)
|
||||
permission = context.GetEffectiveToolPermission(toolName, target)
|
||||
});
|
||||
await RunPermissionLifecycleHooksAsync(
|
||||
"__permission_request__",
|
||||
@@ -4059,7 +4153,7 @@ public partial class AgentLoopService
|
||||
messages,
|
||||
success: true);
|
||||
|
||||
var effectivePerm = context.GetEffectiveToolPermission(toolName);
|
||||
var effectivePerm = context.GetEffectiveToolPermission(toolName, target);
|
||||
|
||||
if (string.Equals(effectivePerm, "Ask", StringComparison.OrdinalIgnoreCase))
|
||||
EmitEvent(AgentEventType.PermissionRequest, toolName, $"권한 확인 필요 · 대상: {target}");
|
||||
|
||||
Reference in New Issue
Block a user