diff --git a/src/ClaudeDo.Worker/Hub/WorkerHub.cs b/src/ClaudeDo.Worker/Hub/WorkerHub.cs index eb19de7..cac4756 100644 --- a/src/ClaudeDo.Worker/Hub/WorkerHub.cs +++ b/src/ClaudeDo.Worker/Hub/WorkerHub.cs @@ -5,6 +5,7 @@ using ClaudeDo.Data.Repositories; using ClaudeDo.Worker.Agents; using ClaudeDo.Worker.Lifecycle; using ClaudeDo.Worker.Planning; +using ClaudeDo.Worker.Prime; using ClaudeDo.Worker.Queue; using ClaudeDo.Worker.Worktrees; using Microsoft.AspNetCore.SignalR; @@ -53,6 +54,7 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub private readonly PlanningAggregator _planningAggregator; private readonly PlanningMergeOrchestrator _planningMergeOrchestrator; private readonly PlanningChainCoordinator _planningChain; + private readonly IPrimeScheduleSignal _primeSignal; public WorkerHub( QueueService queue, @@ -68,7 +70,8 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub IPlanningTerminalLauncher launcher, PlanningAggregator planningAggregator, PlanningMergeOrchestrator planningMergeOrchestrator, - PlanningChainCoordinator planningChain) + PlanningChainCoordinator planningChain, + IPrimeScheduleSignal primeSignal) { _queue = queue; _waker = waker; @@ -84,6 +87,7 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub _planningAggregator = planningAggregator; _planningMergeOrchestrator = planningMergeOrchestrator; _planningChain = planningChain; + _primeSignal = primeSignal; } public async Task QueuePlanningSubtasksAsync(string parentTaskId) @@ -422,5 +426,44 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub catch (InvalidOperationException ex) { throw new HubException(ex.Message); } } + public async Task> ListPrimeSchedules() + { + using var ctx = _dbFactory.CreateDbContext(); + var rows = await new PrimeScheduleRepository(ctx).ListAsync(); + return rows.Select(e => new PrimeScheduleDto( + e.Id, e.StartDate, e.EndDate, e.TimeOfDay, + e.WorkdaysOnly, e.Enabled, e.LastRunAt, e.PromptOverride)).ToList(); + } + + public async Task UpsertPrimeSchedule(PrimeScheduleDto dto) + { + using var ctx = _dbFactory.CreateDbContext(); + var repo = new PrimeScheduleRepository(ctx); + var existing = await repo.GetAsync(dto.Id); + var entity = new ClaudeDo.Data.Models.PrimeScheduleEntity + { + Id = dto.Id == Guid.Empty ? Guid.NewGuid() : dto.Id, + StartDate = dto.StartDate, + EndDate = dto.EndDate, + TimeOfDay = dto.TimeOfDay, + WorkdaysOnly = dto.WorkdaysOnly, + Enabled = dto.Enabled, + PromptOverride = dto.PromptOverride, + CreatedAt = existing?.CreatedAt ?? DateTimeOffset.UtcNow, + LastRunAt = existing?.LastRunAt, + }; + await repo.UpsertAsync(entity); + _primeSignal.Signal(); + return new PrimeScheduleDto(entity.Id, entity.StartDate, entity.EndDate, entity.TimeOfDay, + entity.WorkdaysOnly, entity.Enabled, entity.LastRunAt, entity.PromptOverride); + } + + public async Task DeletePrimeSchedule(Guid id) + { + using var ctx = _dbFactory.CreateDbContext(); + await new PrimeScheduleRepository(ctx).DeleteAsync(id); + _primeSignal.Signal(); + } + private static string? Nullify(string? s) => string.IsNullOrWhiteSpace(s) ? null : s; }