feat(worker): SignalR hub endpoints for planning sessions

This commit is contained in:
mika kuns
2026-04-23 23:26:12 +02:00
parent c048264b95
commit 7b67e35720
2 changed files with 268 additions and 1 deletions

View File

@@ -2,6 +2,7 @@ using System.Reflection;
using ClaudeDo.Data;
using ClaudeDo.Data.Models;
using ClaudeDo.Data.Repositories;
using ClaudeDo.Worker.Planning;
using ClaudeDo.Worker.Services;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
@@ -43,6 +44,8 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub
private readonly WorktreeMaintenanceService _wtMaintenance;
private readonly TaskResetService _resetService;
private readonly TaskMergeService _mergeService;
private readonly PlanningSessionManager _planning;
private readonly IPlanningTerminalLauncher _launcher;
public WorkerHub(
QueueService queue,
@@ -52,7 +55,9 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub
IDbContextFactory<ClaudeDoDbContext> dbFactory,
WorktreeMaintenanceService wtMaintenance,
TaskResetService resetService,
TaskMergeService mergeService)
TaskMergeService mergeService,
PlanningSessionManager planning,
IPlanningTerminalLauncher launcher)
{
_queue = queue;
_agentService = agentService;
@@ -62,6 +67,8 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub
_wtMaintenance = wtMaintenance;
_resetService = resetService;
_mergeService = mergeService;
_planning = planning;
_launcher = launcher;
}
public string Ping() => $"pong v{Version}";
@@ -284,5 +291,44 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub
await _broadcaster.TaskUpdated(dto.TaskId);
}
public async Task<PlanningSessionStartContext> StartPlanningSessionAsync(string taskId)
{
var ctx = await _planning.StartAsync(taskId, Context.ConnectionAborted);
try
{
await _launcher.LaunchStartAsync(ctx, Context.ConnectionAborted);
}
catch (PlanningLaunchException)
{
await _planning.DiscardAsync(taskId, Context.ConnectionAborted);
throw;
}
await Clients.All.SendAsync("TaskUpdated", taskId);
return ctx;
}
public async Task<PlanningSessionResumeContext> ResumePlanningSessionAsync(string taskId)
{
var ctx = await _planning.ResumeAsync(taskId, Context.ConnectionAborted);
await _launcher.LaunchResumeAsync(ctx, Context.ConnectionAborted);
return ctx;
}
public async Task DiscardPlanningSessionAsync(string taskId)
{
await _planning.DiscardAsync(taskId, Context.ConnectionAborted);
await Clients.All.SendAsync("TaskUpdated", taskId);
}
public async Task<int> FinalizePlanningSessionAsync(string taskId, bool queueAgentTasks = true)
{
var count = await _planning.FinalizeAsync(taskId, queueAgentTasks, Context.ConnectionAborted);
await Clients.All.SendAsync("TaskUpdated", taskId);
return count;
}
public Task<int> GetPendingDraftCountAsync(string taskId)
=> _planning.GetPendingDraftCountAsync(taskId, Context.ConnectionAborted);
private static string? Nullify(string? s) => string.IsNullOrWhiteSpace(s) ? null : s;
}