diff --git a/src/ClaudeDo.Worker/Hub/HubBroadcaster.cs b/src/ClaudeDo.Worker/Hub/HubBroadcaster.cs index 467fae9..c0690be 100644 --- a/src/ClaudeDo.Worker/Hub/HubBroadcaster.cs +++ b/src/ClaudeDo.Worker/Hub/HubBroadcaster.cs @@ -1,10 +1,11 @@ using ClaudeDo.Data.Models; using ClaudeDo.Worker.Prime; +using ClaudeDo.Worker.Refine; using Microsoft.AspNetCore.SignalR; namespace ClaudeDo.Worker.Hub; -public sealed class HubBroadcaster : IPrimeBroadcaster +public sealed class HubBroadcaster : IPrimeBroadcaster, IRefineBroadcaster { private readonly IHubContext _hub; @@ -62,4 +63,12 @@ public sealed class HubBroadcaster : IPrimeBroadcaster Task IPrimeBroadcaster.PrepStartedAsync() => PrepStarted(); Task IPrimeBroadcaster.PrepLineAsync(string line) => PrepLine(line); Task IPrimeBroadcaster.PrepFinishedAsync(bool success) => PrepFinished(success); + + public Task RefineStarted(string taskId) => _hub.Clients.All.SendAsync("RefineStarted", taskId); + public Task RefineFinished(string taskId, bool success, string? error) => + _hub.Clients.All.SendAsync("RefineFinished", taskId, success, error); + + Task IRefineBroadcaster.RefineStartedAsync(string taskId) => RefineStarted(taskId); + Task IRefineBroadcaster.RefineFinishedAsync(string taskId, bool success, string? error) => + RefineFinished(taskId, success, error); } diff --git a/src/ClaudeDo.Worker/Hub/WorkerHub.cs b/src/ClaudeDo.Worker/Hub/WorkerHub.cs index 72ac154..959957c 100644 --- a/src/ClaudeDo.Worker/Hub/WorkerHub.cs +++ b/src/ClaudeDo.Worker/Hub/WorkerHub.cs @@ -8,6 +8,7 @@ using ClaudeDo.Worker.Lifecycle; using ClaudeDo.Worker.Planning; using ClaudeDo.Worker.Prime; using ClaudeDo.Worker.Queue; +using ClaudeDo.Worker.Refine; using ClaudeDo.Worker.Report; using ClaudeDo.Worker.Report.Interfaces; using ClaudeDo.Worker.State; @@ -83,6 +84,7 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub private readonly IPrimeRunner _primeRunner; private readonly ITaskStateService _state; private readonly IWeekReportService _report; + private readonly IRefineRunner _refineRunner; public WorkerHub( QueueService queue, @@ -102,7 +104,8 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub IPrimeScheduleSignal primeSignal, IPrimeRunner primeRunner, ITaskStateService state, - IWeekReportService report) + IWeekReportService report, + IRefineRunner refineRunner) { _queue = queue; _waker = waker; @@ -122,6 +125,7 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub _primeRunner = primeRunner; _state = state; _report = report; + _refineRunner = refineRunner; } // Maps the two exceptions service methods throw into client-facing HubExceptions: @@ -541,6 +545,12 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub _primeSignal.Signal(); } + public Task RefineTask(string taskId) + { + _ = _refineRunner.RefineAsync(taskId, CancellationToken.None); + return Task.CompletedTask; + } + public async Task RunDailyPrepNow() { var schedule = new PrimeScheduleDto(Guid.Empty, 0, TimeSpan.Zero, true, null, null); diff --git a/src/ClaudeDo.Worker/Program.cs b/src/ClaudeDo.Worker/Program.cs index 3f06a19..7348efe 100644 --- a/src/ClaudeDo.Worker/Program.cs +++ b/src/ClaudeDo.Worker/Program.cs @@ -12,6 +12,7 @@ using ClaudeDo.Worker.Queue; using ClaudeDo.Worker.Runner; using ClaudeDo.Worker.State; using ClaudeDo.Worker.Prime; +using ClaudeDo.Worker.Refine; using ClaudeDo.Worker.Report; using ClaudeDo.Worker.Report.Interfaces; using ClaudeDo.Worker.Worktrees; @@ -108,6 +109,10 @@ builder.Services.AddSingleton(PrimeSchedulerOptions.Default); builder.Services.AddSingleton(sp => sp.GetRequiredService()); builder.Services.AddHostedService(); +// Refine +builder.Services.AddSingleton(); +builder.Services.AddSingleton(sp => sp.GetRequiredService()); + // QueueService: singleton + hosted service (same instance). builder.Services.AddSingleton(); builder.Services.AddHostedService(sp => sp.GetRequiredService()); diff --git a/tests/ClaudeDo.Worker.Tests/Hub/ClearMyDayHubTests.cs b/tests/ClaudeDo.Worker.Tests/Hub/ClearMyDayHubTests.cs index 402cce2..1fd550c 100644 --- a/tests/ClaudeDo.Worker.Tests/Hub/ClearMyDayHubTests.cs +++ b/tests/ClaudeDo.Worker.Tests/Hub/ClearMyDayHubTests.cs @@ -19,7 +19,7 @@ public sealed class ClearMyDayHubTests : IDisposable var broadcaster = new HubBroadcaster(new CapturingHubContext()); var hub = new WorkerHub( null!, null!, null!, null!, broadcaster, _db.CreateFactory(), - null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!); + null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!); hub.Clients = new FakeHubCallerClients(new RecordingClientProxy()); hub.Context = new FakeHubCallerContext(); return hub; diff --git a/tests/ClaudeDo.Worker.Tests/Hub/PlanningHubTests.cs b/tests/ClaudeDo.Worker.Tests/Hub/PlanningHubTests.cs index 2fba972..1579e3c 100644 --- a/tests/ClaudeDo.Worker.Tests/Hub/PlanningHubTests.cs +++ b/tests/ClaudeDo.Worker.Tests/Hub/PlanningHubTests.cs @@ -55,7 +55,7 @@ public sealed class PlanningHubTests : IDisposable { var hub = new WorkerHub( null!, null!, null!, null!, null!, null!, null!, null!, null!, - _planning, _launcher, null!, null!, null!, null!, null!, null!, null!); + _planning, _launcher, null!, null!, null!, null!, null!, null!, null!, null!); hub.Clients = new FakeHubCallerClients(_proxy); hub.Context = new FakeHubCallerContext(); return hub; diff --git a/tests/ClaudeDo.Worker.Tests/Hub/WorktreeStateHubTests.cs b/tests/ClaudeDo.Worker.Tests/Hub/WorktreeStateHubTests.cs index 87b845b..0043533 100644 --- a/tests/ClaudeDo.Worker.Tests/Hub/WorktreeStateHubTests.cs +++ b/tests/ClaudeDo.Worker.Tests/Hub/WorktreeStateHubTests.cs @@ -19,7 +19,7 @@ public sealed class WorktreeStateHubTests : IDisposable var broadcaster = new HubBroadcaster(new CapturingHubContext()); var hub = new WorkerHub( null!, null!, null!, null!, broadcaster, _db.CreateFactory(), - null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!); + null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!, null!); hub.Clients = new FakeHubCallerClients(new RecordingClientProxy()); hub.Context = new FakeHubCallerContext(); return hub;