refactor: drop the remaining single-implementation interfaces
IBaseDirtyChecker, IInteractiveLaunchSpecService and the LaunchSpec wrapper had one implementation and one caller each; ProcessRunnerAdapter existed only to give a static class an interface, and InstallArtifactLocator used inheritance for two constructor arguments. The external MCP container now shares its singletons through a Share<T> helper instead of 17 near-identical registrations.
This commit is contained in:
@@ -89,7 +89,7 @@ builder.Services.AddSingleton<PendingQuestionRegistry>();
|
||||
builder.Services.AddSingleton<IRepoCloner, GitRepoCloner>();
|
||||
builder.Services.AddSingleton<ISessionSkillRegistry, SessionSkillRegistry>();
|
||||
builder.Services.AddSingleton<ISessionSkillSeeder, SessionSkillSeeder>();
|
||||
builder.Services.AddSingleton<IInteractiveLaunchSpecService, InteractiveLaunchSpecService>();
|
||||
builder.Services.AddSingleton<InteractiveLaunchSpecService>();
|
||||
builder.Services.AddSingleton<TaskRunner>();
|
||||
builder.Services.AddSingleton<WorktreeMaintenanceService>();
|
||||
builder.Services.AddSingleton<TaskResetService>();
|
||||
@@ -112,7 +112,7 @@ builder.Services.AddSingleton<Func<ITaskStateService>>(sp => () => sp.GetRequire
|
||||
// PlanningMergeOrchestrator itself depends on ITaskStateService, so TaskStateService can only
|
||||
// reach it lazily (Func<IActiveMergeState>) — same cycle-breaking shape as the Func above.
|
||||
builder.Services.AddSingleton<Func<IActiveMergeState>>(sp => () => sp.GetRequiredService<PlanningMergeOrchestrator>());
|
||||
builder.Services.AddSingleton<IBaseDirtyChecker, BaseDirtyChecker>();
|
||||
builder.Services.AddSingleton<BaseDirtyChecker>();
|
||||
builder.Services.AddSingleton<ITaskStateService>(sp => new TaskStateService(
|
||||
sp.GetRequiredService<IDbContextFactory<ClaudeDoDbContext>>(),
|
||||
sp.GetRequiredService<HubBroadcaster>(),
|
||||
@@ -120,7 +120,7 @@ builder.Services.AddSingleton<ITaskStateService>(sp => new TaskStateService(
|
||||
sp.GetRequiredService<PlanningChainCoordinator>(),
|
||||
sp.GetRequiredService<RunCancellationRegistry>(),
|
||||
sp.GetRequiredService<Func<IActiveMergeState>>(),
|
||||
sp.GetRequiredService<IBaseDirtyChecker>(),
|
||||
sp.GetRequiredService<BaseDirtyChecker>(),
|
||||
sp.GetRequiredService<ILogger<TaskStateService>>()));
|
||||
|
||||
// Agent file management.
|
||||
@@ -201,12 +201,6 @@ builder.Services.AddScoped<PlanningMcpService>();
|
||||
builder.Services.AddScoped<FindingsStoreLocator>();
|
||||
builder.Services.AddScoped<TaskRunFindingsMcpTools>();
|
||||
builder.Services.AddMcpServer()
|
||||
// Stateless: no Mcp-Session-Id, so a worker restart doesn't 404 the sessions that
|
||||
// outlive it (ConPTY tiles in the UI process, externally registered claude sessions),
|
||||
// and a 2026-07-28 client isn't refused back to the initialize handshake. Nothing here
|
||||
// needs the stateful-only features (sampling, elicitation, resource subscriptions,
|
||||
// unsolicited notifications); in-tool progress works in both modes. Implies no legacy
|
||||
// SSE endpoint — setting EnableLegacySse alongside this throws at startup.
|
||||
.WithHttpTransport(o => o.Stateless = true)
|
||||
.WithTools<PlanningMcpService>()
|
||||
.WithTools<TaskRunMcpService>()
|
||||
@@ -308,27 +302,38 @@ WebApplication? externalApp = null;
|
||||
if (cfg.ExternalMcpPort > 0)
|
||||
{
|
||||
var externalBuilder = WebApplication.CreateBuilder();
|
||||
// Hand the second container the SAME singleton instances, so both apps operate on one
|
||||
// runtime state instead of two parallel copies of the queue/git/merge stack.
|
||||
void Share<T>() where T : class =>
|
||||
externalBuilder.Services.AddSingleton(app.Services.GetRequiredService<T>());
|
||||
|
||||
externalBuilder.Services.AddSingleton(cfg);
|
||||
externalBuilder.Services.AddSingleton(app.Services.GetRequiredService<HubBroadcaster>());
|
||||
externalBuilder.Services.AddSingleton(app.Services.GetRequiredService<QueueService>());
|
||||
externalBuilder.Services.AddSingleton(app.Services.GetRequiredService<OverrideSlotService>());
|
||||
externalBuilder.Services.AddSingleton(app.Services.GetRequiredService<IDbContextFactory<ClaudeDoDbContext>>());
|
||||
externalBuilder.Services.AddSingleton(app.Services.GetRequiredService<ITaskStateService>());
|
||||
externalBuilder.Services.AddSingleton(app.Services.GetRequiredService<IQueueWaker>());
|
||||
Share<HubBroadcaster>();
|
||||
Share<QueueService>();
|
||||
Share<OverrideSlotService>();
|
||||
Share<IDbContextFactory<ClaudeDoDbContext>>();
|
||||
Share<ITaskStateService>();
|
||||
Share<IQueueWaker>();
|
||||
Share<WorktreeManager>();
|
||||
Share<AgentFileService>();
|
||||
Share<TaskResetService>();
|
||||
Share<GitService>();
|
||||
Share<BaseDirtyChecker>();
|
||||
Share<WorktreeMaintenanceService>();
|
||||
Share<TaskMergeService>();
|
||||
Share<PlanningMergeOrchestrator>();
|
||||
Share<InteractiveReviewSubmissionService>();
|
||||
Share<AttachmentStore>();
|
||||
Share<FindingsStore>();
|
||||
|
||||
externalBuilder.Services.AddScoped<ClaudeDoDbContext>(sp =>
|
||||
sp.GetRequiredService<IDbContextFactory<ClaudeDoDbContext>>().CreateDbContext());
|
||||
externalBuilder.Services.AddScoped<TaskRepository>();
|
||||
externalBuilder.Services.AddScoped<ListRepository>();
|
||||
externalBuilder.Services.AddScoped<TaskRunRepository>();
|
||||
externalBuilder.Services.AddSingleton(app.Services.GetRequiredService<WorktreeManager>());
|
||||
externalBuilder.Services.AddSingleton(app.Services.GetRequiredService<AgentFileService>());
|
||||
externalBuilder.Services.AddSingleton(app.Services.GetRequiredService<TaskResetService>());
|
||||
externalBuilder.Services.AddSingleton(app.Services.GetRequiredService<GitService>());
|
||||
externalBuilder.Services.AddSingleton(app.Services.GetRequiredService<IBaseDirtyChecker>());
|
||||
externalBuilder.Services.AddSingleton(app.Services.GetRequiredService<WorktreeMaintenanceService>());
|
||||
externalBuilder.Services.AddSingleton(app.Services.GetRequiredService<TaskMergeService>());
|
||||
externalBuilder.Services.AddSingleton(app.Services.GetRequiredService<PlanningMergeOrchestrator>());
|
||||
externalBuilder.Services.AddSingleton(app.Services.GetRequiredService<InteractiveReviewSubmissionService>());
|
||||
externalBuilder.Services.AddScoped<TaskAttachmentRepository>();
|
||||
externalBuilder.Services.AddSingleton<HandoffRoundTracker>();
|
||||
externalBuilder.Services.AddScoped<FindingsStoreLocator>();
|
||||
externalBuilder.Services.AddScoped<ExternalMcpService>();
|
||||
externalBuilder.Services.AddScoped<BatchMcpTools>();
|
||||
externalBuilder.Services.AddScoped<ListMcpTools>();
|
||||
@@ -336,16 +341,11 @@ if (cfg.ExternalMcpPort > 0)
|
||||
externalBuilder.Services.AddScoped<RunHistoryMcpTools>();
|
||||
externalBuilder.Services.AddScoped<AgentMcpTools>();
|
||||
externalBuilder.Services.AddScoped<LifecycleMcpTools>();
|
||||
externalBuilder.Services.AddSingleton<HandoffRoundTracker>();
|
||||
externalBuilder.Services.AddScoped<HandoffMcpTools>();
|
||||
externalBuilder.Services.AddScoped<AppSettingsMcpTools>();
|
||||
externalBuilder.Services.AddScoped<TaskWaitMcpTools>();
|
||||
externalBuilder.Services.AddScoped<QueueStateMcpTools>();
|
||||
externalBuilder.Services.AddSingleton(app.Services.GetRequiredService<AttachmentStore>());
|
||||
externalBuilder.Services.AddScoped<TaskAttachmentRepository>();
|
||||
externalBuilder.Services.AddScoped<AttachmentMcpTools>();
|
||||
externalBuilder.Services.AddSingleton(app.Services.GetRequiredService<FindingsStore>());
|
||||
externalBuilder.Services.AddScoped<FindingsStoreLocator>();
|
||||
externalBuilder.Services.AddScoped<FindingsMcpTools>();
|
||||
externalBuilder.Services.AddMcpServer()
|
||||
.WithHttpTransport(o => o.Stateless = true)
|
||||
|
||||
Reference in New Issue
Block a user