feat(ui): add settings modal and wire to worker hub

This commit is contained in:
Mika Kuns
2026-04-21 15:55:53 +02:00
parent fca5d57fef
commit e6b37624a1
9 changed files with 644 additions and 5 deletions

View File

@@ -1,12 +1,28 @@
using System.Reflection;
using ClaudeDo.Data;
using ClaudeDo.Data.Models;
using ClaudeDo.Data.Repositories;
using ClaudeDo.Worker.Services;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
namespace ClaudeDo.Worker.Hub;
public record ActiveTaskDto(string Slot, string TaskId, DateTime StartedAt);
public record AppSettingsDto(
string DefaultClaudeInstructions,
string DefaultModel,
int DefaultMaxTurns,
string DefaultPermissionMode,
string WorktreeStrategy,
string? CentralWorktreeRoot,
bool WorktreeAutoCleanupEnabled,
int WorktreeAutoCleanupDays);
public record WorktreeCleanupDto(int Removed);
public record WorktreeResetDto(int Removed, int TasksAffected, bool Blocked, int RunningTasks);
public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub
{
private static readonly string Version =
@@ -15,12 +31,21 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub
private readonly QueueService _queue;
private readonly AgentFileService _agentService;
private readonly HubBroadcaster _broadcaster;
private readonly IDbContextFactory<ClaudeDoDbContext> _dbFactory;
private readonly WorktreeMaintenanceService _wtMaintenance;
public WorkerHub(QueueService queue, AgentFileService agentService, HubBroadcaster broadcaster)
public WorkerHub(
QueueService queue,
AgentFileService agentService,
HubBroadcaster broadcaster,
IDbContextFactory<ClaudeDoDbContext> dbFactory,
WorktreeMaintenanceService wtMaintenance)
{
_queue = queue;
_agentService = agentService;
_broadcaster = broadcaster;
_dbFactory = dbFactory;
_wtMaintenance = wtMaintenance;
}
public string Ping() => $"pong v{Version}";
@@ -71,4 +96,49 @@ public sealed class WorkerHub : Microsoft.AspNetCore.SignalR.Hub
public async Task<List<AgentInfo>> GetAgents() => await _agentService.ScanAsync();
public async Task RefreshAgents() => await _agentService.ScanAsync();
public async Task<AppSettingsDto> GetAppSettings()
{
using var ctx = _dbFactory.CreateDbContext();
var row = await new AppSettingsRepository(ctx).GetAsync();
return new AppSettingsDto(
row.DefaultClaudeInstructions,
row.DefaultModel,
row.DefaultMaxTurns,
row.DefaultPermissionMode,
row.WorktreeStrategy,
row.CentralWorktreeRoot,
row.WorktreeAutoCleanupEnabled,
row.WorktreeAutoCleanupDays);
}
public async Task UpdateAppSettings(AppSettingsDto dto)
{
using var ctx = _dbFactory.CreateDbContext();
var repo = new AppSettingsRepository(ctx);
await repo.UpdateAsync(new AppSettingsEntity
{
Id = AppSettingsEntity.SingletonId,
DefaultClaudeInstructions = dto.DefaultClaudeInstructions ?? "",
DefaultModel = dto.DefaultModel ?? "sonnet",
DefaultMaxTurns = dto.DefaultMaxTurns,
DefaultPermissionMode = dto.DefaultPermissionMode ?? "bypassPermissions",
WorktreeStrategy = dto.WorktreeStrategy ?? "sibling",
CentralWorktreeRoot = dto.CentralWorktreeRoot,
WorktreeAutoCleanupEnabled = dto.WorktreeAutoCleanupEnabled,
WorktreeAutoCleanupDays = dto.WorktreeAutoCleanupDays,
});
}
public async Task<WorktreeCleanupDto> CleanupFinishedWorktrees()
{
var result = await _wtMaintenance.CleanupFinishedAsync();
return new WorktreeCleanupDto(result.Removed);
}
public async Task<WorktreeResetDto> ResetAllWorktrees()
{
var result = await _wtMaintenance.ResetAllAsync();
return new WorktreeResetDto(result.Removed, result.TasksAffected, result.Blocked, result.RunningTasks);
}
}