84 lines
2.9 KiB
C#
84 lines
2.9 KiB
C#
using ClaudeDo.Data;
|
|
using ClaudeDo.Data.Git;
|
|
using ClaudeDo.Data.Repositories;
|
|
using ClaudeDo.Worker.Config;
|
|
using ClaudeDo.Worker.Hub;
|
|
using ClaudeDo.Worker.Runner;
|
|
using ClaudeDo.Worker.Services;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
var cfg = WorkerConfig.Load();
|
|
|
|
var builder = WebApplication.CreateBuilder(args);
|
|
|
|
// When launched by the Windows SCM, speak the Service Control Protocol so SCM
|
|
// doesn't think we crashed (~30s timeout). No-op when running interactively.
|
|
builder.Host.UseWindowsService(o => o.ServiceName = "ClaudeDoWorker");
|
|
|
|
builder.Services.AddDbContextFactory<ClaudeDoDbContext>(opt =>
|
|
opt.UseSqlite($"Data Source={cfg.DbPath}"));
|
|
|
|
builder.Services.AddSingleton(cfg);
|
|
builder.Services.AddHostedService<StaleTaskRecovery>();
|
|
builder.Services.AddSignalR().AddJsonProtocol(options =>
|
|
{
|
|
options.PayloadSerializerOptions.Converters.Add(new System.Text.Json.Serialization.JsonStringEnumConverter());
|
|
});
|
|
|
|
// Runner stack.
|
|
builder.Services.AddSingleton<IClaudeProcess, ClaudeProcess>();
|
|
builder.Services.AddSingleton<HubBroadcaster>();
|
|
builder.Services.AddSingleton<GitService>();
|
|
builder.Services.AddSingleton<WorktreeManager>();
|
|
builder.Services.AddSingleton<ClaudeArgsBuilder>();
|
|
builder.Services.AddSingleton<TaskRunner>();
|
|
builder.Services.AddSingleton<WorktreeMaintenanceService>();
|
|
builder.Services.AddSingleton<TaskResetService>();
|
|
builder.Services.AddSingleton<TaskMergeService>();
|
|
|
|
// Agent file management.
|
|
var agentsDir = Path.Combine(ClaudeDo.Data.Paths.AppDataRoot(), "agents");
|
|
Directory.CreateDirectory(agentsDir);
|
|
builder.Services.AddSingleton(new AgentFileService(agentsDir));
|
|
|
|
var defaultAgentsBundleDir = Path.Combine(AppContext.BaseDirectory, "DefaultAgents");
|
|
builder.Services.AddSingleton(sp => new DefaultAgentSeeder(
|
|
defaultAgentsBundleDir,
|
|
agentsDir,
|
|
sp.GetService<Microsoft.Extensions.Logging.ILogger<DefaultAgentSeeder>>()));
|
|
|
|
// QueueService: singleton + hosted service (same instance).
|
|
builder.Services.AddSingleton<QueueService>();
|
|
builder.Services.AddHostedService(sp => sp.GetRequiredService<QueueService>());
|
|
|
|
// Loopback-only bind. Firewall is irrelevant for 127.0.0.1.
|
|
builder.WebHost.UseUrls($"http://127.0.0.1:{cfg.SignalRPort}");
|
|
|
|
var app = builder.Build();
|
|
|
|
using (var scope = app.Services.CreateScope())
|
|
{
|
|
ClaudeDoDbContext.MigrateAndConfigure(
|
|
scope.ServiceProvider.GetRequiredService<ClaudeDoDbContext>());
|
|
}
|
|
|
|
try
|
|
{
|
|
var seeder = app.Services.GetRequiredService<DefaultAgentSeeder>();
|
|
var seedResult = await seeder.SeedMissingAsync();
|
|
app.Logger.LogInformation(
|
|
"Default agents seeded: {Copied} copied, {Skipped} already present",
|
|
seedResult.Copied, seedResult.Skipped);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
app.Logger.LogWarning(ex, "Default agent seeding failed");
|
|
}
|
|
|
|
app.MapHub<WorkerHub>("/hub");
|
|
|
|
app.Logger.LogInformation("ClaudeDo.Worker listening on http://127.0.0.1:{Port} (db: {Db})",
|
|
cfg.SignalRPort, cfg.DbPath);
|
|
|
|
app.Run();
|