- claude-code 선택적 탐색 흐름을 참고해 Cowork/Code 시스템 프롬프트에서 folder_map 상시 선행 지시를 완화하고 glob/grep 기반 좁은 탐색을 우선하도록 조정함 - FolderMapTool 기본 depth를 2로, include_files 기본값을 false로 낮추고 MultiReadTool 최대 파일 수를 8개로 줄여 초기 과탐색 폭을 보수적으로 조정함 - AgentLoopExplorationPolicy partial을 추가해 탐색 범위 분류, broad-scan corrective hint, exploration_breadth 성능 로그를 연결함 - AgentLoopService에 탐색 범위 가이드 주입과 실행 중 탐색 폭 추적을 추가하고, 좁은 질문에서 반복적인 folder_map/대량 multi_read를 교정하도록 정리함 - DocxToHtmlConverter nullable 경고를 수정해 Release 빌드 경고 0 / 오류 0 기준을 다시 충족함 - README와 docs/DEVELOPMENT.md에 2026-04-09 10:36 (KST) 기준 개발 이력을 반영함
This commit is contained in:
@@ -44,8 +44,8 @@ public class SubAgentTool : IAgentTool
|
||||
|
||||
public Task<ToolResult> ExecuteAsync(JsonElement args, AgentContext context, CancellationToken ct = default)
|
||||
{
|
||||
var task = args.TryGetProperty("task", out var t) ? t.GetString() ?? "" : "";
|
||||
var id = args.TryGetProperty("id", out var i) ? i.GetString() ?? "" : "";
|
||||
var task = args.SafeTryGetProperty("task", out var t) ? t.SafeGetString() ?? "" : "";
|
||||
var id = args.SafeTryGetProperty("id", out var i) ? i.SafeGetString() ?? "" : "";
|
||||
|
||||
if (string.IsNullOrWhiteSpace(task) || string.IsNullOrWhiteSpace(id))
|
||||
return Task.FromResult(ToolResult.Fail("task and id are required."));
|
||||
@@ -72,11 +72,15 @@ public class SubAgentTool : IAgentTool
|
||||
StartedAt = DateTime.Now,
|
||||
};
|
||||
|
||||
// P2: 부모 취소 토큰 연동 — 부모 에이전트 중지 시 자식도 즉시 취소
|
||||
var cts = CancellationTokenSource.CreateLinkedTokenSource(ct);
|
||||
subTask.Cts = cts;
|
||||
|
||||
subTask.RunTask = System.Threading.Tasks.Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await RunSubAgentAsync(id, task, context).ConfigureAwait(false);
|
||||
var result = await RunSubAgentAsync(id, task, context, cts.Token).ConfigureAwait(false);
|
||||
subTask.Result = result;
|
||||
subTask.Success = true;
|
||||
NotifyStatus(new SubAgentStatusEvent
|
||||
@@ -89,6 +93,20 @@ public class SubAgentTool : IAgentTool
|
||||
Timestamp = DateTime.Now,
|
||||
});
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
subTask.Result = "Cancelled: parent agent was stopped.";
|
||||
subTask.Success = false;
|
||||
NotifyStatus(new SubAgentStatusEvent
|
||||
{
|
||||
Id = id,
|
||||
Task = task,
|
||||
Status = SubAgentRunStatus.Failed,
|
||||
Summary = $"Sub-agent '{id}' cancelled.",
|
||||
Result = subTask.Result,
|
||||
Timestamp = DateTime.Now,
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
subTask.Result = $"Error: {ex.Message}";
|
||||
@@ -106,8 +124,9 @@ public class SubAgentTool : IAgentTool
|
||||
finally
|
||||
{
|
||||
subTask.CompletedAt = DateTime.Now;
|
||||
cts.Dispose();
|
||||
}
|
||||
}, CancellationToken.None);
|
||||
}, cts.Token);
|
||||
|
||||
lock (_lock)
|
||||
_activeTasks[id] = subTask;
|
||||
@@ -125,7 +144,7 @@ public class SubAgentTool : IAgentTool
|
||||
$"Sub-agent '{id}' started.\nTask: {task}\nUse wait_agents later to collect the result."));
|
||||
}
|
||||
|
||||
private static async Task<string> RunSubAgentAsync(string id, string task, AgentContext parentContext)
|
||||
private static async Task<string> RunSubAgentAsync(string id, string task, AgentContext parentContext, CancellationToken ct)
|
||||
{
|
||||
var settings = CreateSubAgentSettings(parentContext);
|
||||
using var llm = new LlmService(settings);
|
||||
@@ -150,7 +169,7 @@ public class SubAgentTool : IAgentTool
|
||||
}
|
||||
};
|
||||
|
||||
var finalText = await loop.RunAsync(messages, CancellationToken.None).ConfigureAwait(false);
|
||||
var finalText = await loop.RunAsync(messages, ct).ConfigureAwait(false);
|
||||
|
||||
var eventSummary = SummarizeEvents(loop.Events);
|
||||
var sb = new StringBuilder();
|
||||
@@ -451,16 +470,16 @@ public class WaitAgentsTool : IAgentTool
|
||||
public async Task<ToolResult> ExecuteAsync(JsonElement args, AgentContext context, CancellationToken ct = default)
|
||||
{
|
||||
List<string>? ids = null;
|
||||
if (args.TryGetProperty("ids", out var idsEl) && idsEl.ValueKind == JsonValueKind.Array)
|
||||
if (args.SafeTryGetProperty("ids", out var idsEl) && idsEl.ValueKind == JsonValueKind.Array)
|
||||
{
|
||||
ids = idsEl.EnumerateArray()
|
||||
.Where(x => x.ValueKind == JsonValueKind.String)
|
||||
.Select(x => x.GetString() ?? "")
|
||||
.Select(x => x.SafeGetString() ?? "")
|
||||
.Where(x => !string.IsNullOrWhiteSpace(x))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
var completedOnly = args.TryGetProperty("completed_only", out var completedEl) &&
|
||||
var completedOnly = args.SafeTryGetProperty("completed_only", out var completedEl) &&
|
||||
completedEl.ValueKind == JsonValueKind.True;
|
||||
|
||||
var result = await SubAgentTool.WaitAsync(ids, completedOnly, ct).ConfigureAwait(false);
|
||||
@@ -477,6 +496,7 @@ public class SubAgentTask
|
||||
public bool Success { get; set; }
|
||||
public string? Result { get; set; }
|
||||
public Task? RunTask { get; set; }
|
||||
public CancellationTokenSource? Cts { get; set; }
|
||||
}
|
||||
|
||||
public enum SubAgentRunStatus
|
||||
|
||||
Reference in New Issue
Block a user