feat(worker): register planning services and add Merge-all hub methods
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -46,6 +46,8 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub
|
|||||||
private readonly TaskMergeService _mergeService;
|
private readonly TaskMergeService _mergeService;
|
||||||
private readonly PlanningSessionManager _planning;
|
private readonly PlanningSessionManager _planning;
|
||||||
private readonly IPlanningTerminalLauncher _launcher;
|
private readonly IPlanningTerminalLauncher _launcher;
|
||||||
|
private readonly PlanningAggregator _planningAggregator;
|
||||||
|
private readonly PlanningMergeOrchestrator _planningMergeOrchestrator;
|
||||||
|
|
||||||
public WorkerHub(
|
public WorkerHub(
|
||||||
QueueService queue,
|
QueueService queue,
|
||||||
@@ -57,7 +59,9 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub
|
|||||||
TaskResetService resetService,
|
TaskResetService resetService,
|
||||||
TaskMergeService mergeService,
|
TaskMergeService mergeService,
|
||||||
PlanningSessionManager planning,
|
PlanningSessionManager planning,
|
||||||
IPlanningTerminalLauncher launcher)
|
IPlanningTerminalLauncher launcher,
|
||||||
|
PlanningAggregator planningAggregator,
|
||||||
|
PlanningMergeOrchestrator planningMergeOrchestrator)
|
||||||
{
|
{
|
||||||
_queue = queue;
|
_queue = queue;
|
||||||
_agentService = agentService;
|
_agentService = agentService;
|
||||||
@@ -69,6 +73,8 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub
|
|||||||
_mergeService = mergeService;
|
_mergeService = mergeService;
|
||||||
_planning = planning;
|
_planning = planning;
|
||||||
_launcher = launcher;
|
_launcher = launcher;
|
||||||
|
_planningAggregator = planningAggregator;
|
||||||
|
_planningMergeOrchestrator = planningMergeOrchestrator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Ping() => $"pong v{Version}";
|
public string Ping() => $"pong v{Version}";
|
||||||
@@ -330,5 +336,55 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub
|
|||||||
public Task<int> GetPendingDraftCountAsync(string taskId)
|
public Task<int> GetPendingDraftCountAsync(string taskId)
|
||||||
=> _planning.GetPendingDraftCountAsync(taskId, Context.ConnectionAborted);
|
=> _planning.GetPendingDraftCountAsync(taskId, Context.ConnectionAborted);
|
||||||
|
|
||||||
|
public async Task<IReadOnlyList<SubtaskDiffDto>> GetPlanningAggregate(string planningTaskId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var diffs = await _planningAggregator.GetAggregatedDiffAsync(planningTaskId, CancellationToken.None);
|
||||||
|
return diffs.Select(d => new SubtaskDiffDto(
|
||||||
|
d.SubtaskId, d.Title, d.BranchName, d.BaseCommit, d.HeadCommit, d.DiffStat, d.UnifiedDiff)).ToList();
|
||||||
|
}
|
||||||
|
catch (KeyNotFoundException) { throw new HubException("planning task not found"); }
|
||||||
|
catch (InvalidOperationException ex) { throw new HubException(ex.Message); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<CombinedDiffResultDto> BuildPlanningIntegrationBranch(string planningTaskId, string targetBranch)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = await _planningAggregator.BuildIntegrationBranchAsync(
|
||||||
|
planningTaskId, targetBranch ?? "", CancellationToken.None);
|
||||||
|
return result switch
|
||||||
|
{
|
||||||
|
CombinedDiffResult.Ok ok => new CombinedDiffResultDto(
|
||||||
|
true, ok.Value.IntegrationBranch, ok.Value.UnifiedDiff, null, null),
|
||||||
|
CombinedDiffResult.Failed f => new CombinedDiffResultDto(
|
||||||
|
false, null, null, f.Value.FirstConflictSubtaskId, f.Value.ConflictedFiles),
|
||||||
|
_ => throw new InvalidOperationException("unknown result type"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (KeyNotFoundException) { throw new HubException("planning task not found"); }
|
||||||
|
catch (InvalidOperationException ex) { throw new HubException(ex.Message); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task MergeAllPlanning(string planningTaskId, string targetBranch)
|
||||||
|
{
|
||||||
|
try { await _planningMergeOrchestrator.StartAsync(planningTaskId, targetBranch ?? "", CancellationToken.None); }
|
||||||
|
catch (KeyNotFoundException) { throw new HubException("planning task not found"); }
|
||||||
|
catch (InvalidOperationException ex) { throw new HubException(ex.Message); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ContinuePlanningMerge(string planningTaskId)
|
||||||
|
{
|
||||||
|
try { await _planningMergeOrchestrator.ContinueAsync(planningTaskId, CancellationToken.None); }
|
||||||
|
catch (InvalidOperationException ex) { throw new HubException(ex.Message); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task AbortPlanningMerge(string planningTaskId)
|
||||||
|
{
|
||||||
|
try { await _planningMergeOrchestrator.AbortAsync(planningTaskId, CancellationToken.None); }
|
||||||
|
catch (InvalidOperationException ex) { throw new HubException(ex.Message); }
|
||||||
|
}
|
||||||
|
|
||||||
private static string? Nullify(string? s) => string.IsNullOrWhiteSpace(s) ? null : s;
|
private static string? Nullify(string? s) => string.IsNullOrWhiteSpace(s) ? null : s;
|
||||||
}
|
}
|
||||||
|
|||||||
17
src/ClaudeDo.Worker/Planning/PlanningWireDtos.cs
Normal file
17
src/ClaudeDo.Worker/Planning/PlanningWireDtos.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
namespace ClaudeDo.Worker.Planning;
|
||||||
|
|
||||||
|
public sealed record SubtaskDiffDto(
|
||||||
|
string SubtaskId,
|
||||||
|
string Title,
|
||||||
|
string BranchName,
|
||||||
|
string BaseCommit,
|
||||||
|
string HeadCommit,
|
||||||
|
string? DiffStat,
|
||||||
|
string UnifiedDiff);
|
||||||
|
|
||||||
|
public sealed record CombinedDiffResultDto(
|
||||||
|
bool Success,
|
||||||
|
string? IntegrationBranch,
|
||||||
|
string? UnifiedDiff,
|
||||||
|
string? FirstConflictSubtaskId,
|
||||||
|
IReadOnlyList<string>? ConflictedFiles);
|
||||||
@@ -36,6 +36,8 @@ builder.Services.AddSingleton<TaskRunner>();
|
|||||||
builder.Services.AddSingleton<WorktreeMaintenanceService>();
|
builder.Services.AddSingleton<WorktreeMaintenanceService>();
|
||||||
builder.Services.AddSingleton<TaskResetService>();
|
builder.Services.AddSingleton<TaskResetService>();
|
||||||
builder.Services.AddSingleton<TaskMergeService>();
|
builder.Services.AddSingleton<TaskMergeService>();
|
||||||
|
builder.Services.AddSingleton<PlanningAggregator>();
|
||||||
|
builder.Services.AddSingleton<PlanningMergeOrchestrator>();
|
||||||
|
|
||||||
// Agent file management.
|
// Agent file management.
|
||||||
var agentsDir = Path.Combine(ClaudeDo.Data.Paths.AppDataRoot(), "agents");
|
var agentsDir = Path.Combine(ClaudeDo.Data.Paths.AppDataRoot(), "agents");
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ public sealed class PlanningHubTests : IDisposable
|
|||||||
{
|
{
|
||||||
var hub = new WorkerHub(
|
var hub = new WorkerHub(
|
||||||
null!, null!, null!, null!, null!, null!, null!, null!,
|
null!, null!, null!, null!, null!, null!, null!, null!,
|
||||||
_planning, _launcher);
|
_planning, _launcher, null!, null!);
|
||||||
hub.Clients = new FakeHubCallerClients(_proxy);
|
hub.Clients = new FakeHubCallerClients(_proxy);
|
||||||
hub.Context = new FakeHubCallerContext();
|
hub.Context = new FakeHubCallerContext();
|
||||||
return hub;
|
return hub;
|
||||||
|
|||||||
Reference in New Issue
Block a user