refactor: fold single-consumer helper types into their owners

Consolidate small single-purpose types into the files that own them:
StreamResult into StreamAnalyzer, the Planning context records into
PlanningSessionContext, PrimeClock/PrimeSchedulerOptions into PrimeScheduler,
AgentMcpTools into LifecycleMcpTools, the locator subclasses into
InstallArtifactLocator, LogLineViewModel into DetailsIslandViewModel,
RepoImportItemViewModel into its modal, and StepViewModel into InstallPageViewModel.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
mika kuns
2026-05-30 15:47:46 +02:00
parent 25ee623c42
commit ce9fadc0b5
20 changed files with 121 additions and 141 deletions

View File

@@ -10,6 +10,18 @@ using Microsoft.Extensions.DependencyInjection;
namespace ClaudeDo.Installer.Pages.InstallPage; namespace ClaudeDo.Installer.Pages.InstallPage;
public partial class StepViewModel : ObservableObject
{
public string Name { get; }
[ObservableProperty] private StepStatus _status = StepStatus.Pending;
[ObservableProperty] private bool _isExpanded;
public ObservableCollection<string> Messages { get; } = [];
public StepViewModel(string name) => Name = name;
}
public partial class InstallPageViewModel : ObservableObject, IInstallerPage public partial class InstallPageViewModel : ObservableObject, IInstallerPage
{ {
private readonly InstallContext _context; private readonly InstallContext _context;

View File

@@ -1,17 +0,0 @@
using System.Collections.ObjectModel;
using ClaudeDo.Installer.Core;
using CommunityToolkit.Mvvm.ComponentModel;
namespace ClaudeDo.Installer.Pages.InstallPage;
public partial class StepViewModel : ObservableObject
{
public string Name { get; }
[ObservableProperty] private StepStatus _status = StepStatus.Pending;
[ObservableProperty] private bool _isExpanded;
public ObservableCollection<string> Messages { get; } = [];
public StepViewModel(string name) => Name = name;
}

View File

@@ -1,5 +1,17 @@
namespace ClaudeDo.Ui.Services; namespace ClaudeDo.Ui.Services;
public sealed class InstallerLocator : InstallArtifactLocator
{
protected override string Subdir => "uninstaller";
protected override string ExeName => "ClaudeDo.Installer.exe";
}
public sealed class WorkerLocator : InstallArtifactLocator
{
protected override string Subdir => "worker";
protected override string ExeName => "ClaudeDo.Worker.exe";
}
/// <summary> /// <summary>
/// Locates an executable inside a ClaudeDo install: walk up from the running /// Locates an executable inside a ClaudeDo install: walk up from the running
/// directory to the folder containing install.json, otherwise read the /// directory to the folder containing install.json, otherwise read the

View File

@@ -1,7 +0,0 @@
namespace ClaudeDo.Ui.Services;
public sealed class InstallerLocator : InstallArtifactLocator
{
protected override string Subdir => "uninstaller";
protected override string ExeName => "ClaudeDo.Installer.exe";
}

View File

@@ -1,7 +0,0 @@
namespace ClaudeDo.Ui.Services;
public sealed class WorkerLocator : InstallArtifactLocator
{
protected override string Subdir => "worker";
protected override string ExeName => "ClaudeDo.Worker.exe";
}

View File

@@ -13,6 +13,37 @@ using Microsoft.Extensions.DependencyInjection;
namespace ClaudeDo.Ui.ViewModels.Islands; namespace ClaudeDo.Ui.ViewModels.Islands;
public enum LogKind { Sys, Tool, Claude, Stdout, Stderr, Done, Msg }
public sealed class LogLineViewModel
{
public required LogKind Kind { get; init; }
public required string Text { get; init; }
public string TimestampFormatted { get; } = DateTime.Now.ToString("HH:mm:ss");
public string KindMarker => Kind switch
{
LogKind.Sys => "sys",
LogKind.Tool => "tool",
LogKind.Claude => "claude",
LogKind.Stdout => "out",
LogKind.Stderr => "err",
LogKind.Done => "done",
LogKind.Msg => "claude",
_ => "",
};
public string ClassName => Kind switch
{
LogKind.Sys => "log-sys",
LogKind.Tool => "log-tool",
LogKind.Claude => "log-claude",
LogKind.Stdout => "log-stdout",
LogKind.Stderr => "log-stderr",
LogKind.Done => "log-done",
LogKind.Msg => "log-msg",
_ => "",
};
}
public sealed partial class DetailsIslandViewModel : ViewModelBase public sealed partial class DetailsIslandViewModel : ViewModelBase
{ {
private readonly IDbContextFactory<ClaudeDoDbContext> _dbFactory; private readonly IDbContextFactory<ClaudeDoDbContext> _dbFactory;

View File

@@ -1,32 +0,0 @@
namespace ClaudeDo.Ui.ViewModels.Islands;
public enum LogKind { Sys, Tool, Claude, Stdout, Stderr, Done, Msg }
public sealed class LogLineViewModel
{
public required LogKind Kind { get; init; }
public required string Text { get; init; }
public string TimestampFormatted { get; } = DateTime.Now.ToString("HH:mm:ss");
public string KindMarker => Kind switch
{
LogKind.Sys => "sys",
LogKind.Tool => "tool",
LogKind.Claude => "claude",
LogKind.Stdout => "out",
LogKind.Stderr => "err",
LogKind.Done => "done",
LogKind.Msg => "claude",
_ => "",
};
public string ClassName => Kind switch
{
LogKind.Sys => "log-sys",
LogKind.Tool => "log-tool",
LogKind.Claude => "log-claude",
LogKind.Stdout => "log-stdout",
LogKind.Stderr => "log-stderr",
LogKind.Done => "log-done",
LogKind.Msg => "log-msg",
_ => "",
};
}

View File

@@ -1,18 +0,0 @@
using CommunityToolkit.Mvvm.ComponentModel;
namespace ClaudeDo.Ui.ViewModels.Modals;
public sealed partial class RepoImportItemViewModel : ViewModelBase
{
public string Name { get; init; } = "";
public string FullPath { get; init; } = "";
// True when a list already points at this path. Such rows are shown ticked + disabled.
public bool AlreadyAdded { get; init; }
public bool CanToggle => !AlreadyAdded;
[ObservableProperty] private bool _isChecked;
// Driven by the search filter; the row collapses when it doesn't match.
[ObservableProperty] private bool _isVisible = true;
}

View File

@@ -10,6 +10,21 @@ using Microsoft.EntityFrameworkCore;
namespace ClaudeDo.Ui.ViewModels.Modals; namespace ClaudeDo.Ui.ViewModels.Modals;
public sealed partial class RepoImportItemViewModel : ViewModelBase
{
public string Name { get; init; } = "";
public string FullPath { get; init; } = "";
// True when a list already points at this path. Such rows are shown ticked + disabled.
public bool AlreadyAdded { get; init; }
public bool CanToggle => !AlreadyAdded;
[ObservableProperty] private bool _isChecked;
// Driven by the search filter; the row collapses when it doesn't match.
[ObservableProperty] private bool _isVisible = true;
}
public sealed partial class RepoImportModalViewModel : ViewModelBase public sealed partial class RepoImportModalViewModel : ViewModelBase
{ {
private readonly IDbContextFactory<ClaudeDoDbContext> _dbFactory; private readonly IDbContextFactory<ClaudeDoDbContext> _dbFactory;

View File

@@ -1,18 +0,0 @@
using System.ComponentModel;
using ClaudeDo.Data.Models;
using ClaudeDo.Worker.Agents;
using ModelContextProtocol.Server;
namespace ClaudeDo.Worker.External;
[McpServerToolType]
public sealed class AgentMcpTools
{
private readonly AgentFileService _agents;
public AgentMcpTools(AgentFileService agents) => _agents = agents;
[McpServerTool, Description("List available agent definition files (name, description, path) for use as a task's agent path.")]
public async Task<IReadOnlyList<AgentInfo>> ListAgents(CancellationToken cancellationToken)
=> await _agents.ScanAsync(cancellationToken);
}

View File

@@ -1,11 +1,25 @@
using System.ComponentModel; using System.ComponentModel;
using ClaudeDo.Data.Models;
using ClaudeDo.Data.Repositories; using ClaudeDo.Data.Repositories;
using ClaudeDo.Worker.Agents;
using ClaudeDo.Worker.Lifecycle; using ClaudeDo.Worker.Lifecycle;
using ModelContextProtocol.Server; using ModelContextProtocol.Server;
using TaskStatus = ClaudeDo.Data.Models.TaskStatus; using TaskStatus = ClaudeDo.Data.Models.TaskStatus;
namespace ClaudeDo.Worker.External; namespace ClaudeDo.Worker.External;
[McpServerToolType]
public sealed class AgentMcpTools
{
private readonly AgentFileService _agents;
public AgentMcpTools(AgentFileService agents) => _agents = agents;
[McpServerTool, Description("List available agent definition files (name, description, path) for use as a task's agent path.")]
public async Task<IReadOnlyList<AgentInfo>> ListAgents(CancellationToken cancellationToken)
=> await _agents.ScanAsync(cancellationToken);
}
[McpServerToolType] [McpServerToolType]
public sealed class LifecycleMcpTools public sealed class LifecycleMcpTools
{ {

View File

@@ -1,6 +0,0 @@
namespace ClaudeDo.Worker.Planning;
public sealed record InteractiveLaunchContext(
string TaskId,
string WorkingDir,
string InitialPrompt);

View File

@@ -1,6 +0,0 @@
namespace ClaudeDo.Worker.Planning;
public sealed class PlanningMcpContext
{
public required string ParentTaskId { get; init; }
}

View File

@@ -1,5 +1,20 @@
namespace ClaudeDo.Worker.Planning; namespace ClaudeDo.Worker.Planning;
public sealed record PlanningSessionFiles(
string SessionDirectory,
string SystemPromptPath,
string InitialPromptPath);
public sealed record InteractiveLaunchContext(
string TaskId,
string WorkingDir,
string InitialPrompt);
public sealed class PlanningMcpContext
{
public required string ParentTaskId { get; init; }
}
public sealed record PlanningSessionStartContext( public sealed record PlanningSessionStartContext(
string ParentTaskId, string ParentTaskId,
string WorkingDir, string WorkingDir,

View File

@@ -1,6 +0,0 @@
namespace ClaudeDo.Worker.Planning;
public sealed record PlanningSessionFiles(
string SessionDirectory,
string SystemPromptPath,
string InitialPromptPath);

View File

@@ -1,5 +0,0 @@
namespace ClaudeDo.Worker.Prime;
public sealed class PrimeClock : IPrimeClock
{
public DateTimeOffset Now => DateTimeOffset.Now;
}

View File

@@ -5,6 +5,17 @@ using Microsoft.Extensions.Hosting;
namespace ClaudeDo.Worker.Prime; namespace ClaudeDo.Worker.Prime;
public sealed class PrimeClock : IPrimeClock
{
public DateTimeOffset Now => DateTimeOffset.Now;
}
public sealed record PrimeSchedulerOptions(TimeSpan CatchUpWindow)
{
public static PrimeSchedulerOptions Default { get; } =
new(TimeSpan.FromMinutes(30));
}
public sealed class PrimeScheduler : BackgroundService public sealed class PrimeScheduler : BackgroundService
{ {
private readonly IDbContextFactory<ClaudeDoDbContext> _dbFactory; private readonly IDbContextFactory<ClaudeDoDbContext> _dbFactory;

View File

@@ -1,7 +0,0 @@
namespace ClaudeDo.Worker.Prime;
public sealed record PrimeSchedulerOptions(TimeSpan CatchUpWindow)
{
public static PrimeSchedulerOptions Default { get; } =
new(TimeSpan.FromMinutes(30));
}

View File

@@ -2,6 +2,17 @@ using System.Text.Json;
namespace ClaudeDo.Worker.Runner; namespace ClaudeDo.Worker.Runner;
public sealed class StreamResult
{
public string? ResultMarkdown { get; set; }
public string? StructuredOutputJson { get; set; }
public string? SessionId { get; set; }
public int TurnCount { get; set; }
public int TokensIn { get; set; }
public int TokensOut { get; set; }
public int ApiRetryCount { get; set; }
}
public sealed class StreamAnalyzer public sealed class StreamAnalyzer
{ {
private string? _resultMarkdown; private string? _resultMarkdown;

View File

@@ -1,12 +0,0 @@
namespace ClaudeDo.Worker.Runner;
public sealed class StreamResult
{
public string? ResultMarkdown { get; set; }
public string? StructuredOutputJson { get; set; }
public string? SessionId { get; set; }
public int TurnCount { get; set; }
public int TokensIn { get; set; }
public int TokensOut { get; set; }
public int ApiRetryCount { get; set; }
}