|
|
|
@@ -10,7 +10,6 @@ using Microsoft.Extensions.DependencyInjection;
|
|
|
|
|
|
|
|
|
|
namespace ClaudeDo.Ui.Services;
|
|
|
|
|
|
|
|
|
|
public record ActiveTask(string Slot, string TaskId, DateTime StartedAt);
|
|
|
|
|
public sealed record WorkerLogEntry(string Message, WorkerLogLevel Level, DateTime TimestampUtc);
|
|
|
|
|
|
|
|
|
|
sealed class IndefiniteRetryPolicy : IRetryPolicy
|
|
|
|
@@ -41,7 +40,7 @@ public partial class WorkerClient : ObservableObject, IAsyncDisposable, IWorkerC
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
private bool _isReconnecting;
|
|
|
|
|
|
|
|
|
|
public ObservableCollection<ActiveTask> ActiveTasks { get; } = new();
|
|
|
|
|
public ObservableCollection<ActiveTaskDto> ActiveTasks { get; } = new();
|
|
|
|
|
|
|
|
|
|
public event Action<string, string, DateTime>? TaskStartedEvent;
|
|
|
|
|
public event Action<string, string, string, DateTime>? TaskFinishedEvent;
|
|
|
|
@@ -77,7 +76,7 @@ public partial class WorkerClient : ObservableObject, IAsyncDisposable, IWorkerC
|
|
|
|
|
|
|
|
|
|
public string? LastApproveTarget { get; private set; }
|
|
|
|
|
|
|
|
|
|
public IReadOnlyList<ActiveTask> GetActiveTasks() => ActiveTasks.ToList();
|
|
|
|
|
public IReadOnlyList<ActiveTaskDto> GetActiveTasks() => ActiveTasks.ToList();
|
|
|
|
|
|
|
|
|
|
public WorkerClient(string signalRUrl)
|
|
|
|
|
{
|
|
|
|
@@ -118,7 +117,7 @@ public partial class WorkerClient : ObservableObject, IAsyncDisposable, IWorkerC
|
|
|
|
|
{
|
|
|
|
|
Dispatcher.UIThread.Post(() =>
|
|
|
|
|
{
|
|
|
|
|
ActiveTasks.Add(new ActiveTask(slot, taskId, startedAt));
|
|
|
|
|
ActiveTasks.Add(new ActiveTaskDto(slot, taskId, startedAt));
|
|
|
|
|
TaskStartedEvent?.Invoke(slot, taskId, startedAt);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
@@ -417,7 +416,7 @@ public partial class WorkerClient : ObservableObject, IAsyncDisposable, IWorkerC
|
|
|
|
|
{
|
|
|
|
|
ActiveTasks.Clear();
|
|
|
|
|
foreach (var a in active)
|
|
|
|
|
ActiveTasks.Add(new ActiveTask(a.Slot, a.TaskId, a.StartedAt));
|
|
|
|
|
ActiveTasks.Add(new ActiveTaskDto(a.Slot, a.TaskId, a.StartedAt));
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
catch (HubException)
|
|
|
|
@@ -712,177 +711,5 @@ public partial class WorkerClient : ObservableObject, IAsyncDisposable, IWorkerC
|
|
|
|
|
=> await FinalizePlanningSessionAsync(taskId, queueAgentTasks, ct);
|
|
|
|
|
async Task<int> IWorkerClient.GetPendingDraftCountAsync(string taskId, CancellationToken ct)
|
|
|
|
|
=> await GetPendingDraftCountAsync(taskId, ct);
|
|
|
|
|
|
|
|
|
|
// DTOs for deserializing hub responses
|
|
|
|
|
private sealed class ActiveTaskDto
|
|
|
|
|
{
|
|
|
|
|
public string Slot { get; set; } = "";
|
|
|
|
|
public string TaskId { get; set; } = "";
|
|
|
|
|
public DateTime StartedAt { get; set; }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public sealed record AppSettingsDto(
|
|
|
|
|
string DefaultClaudeInstructions,
|
|
|
|
|
string DefaultModel,
|
|
|
|
|
int DefaultMaxTurns,
|
|
|
|
|
string DefaultPermissionMode,
|
|
|
|
|
int MaxParallelExecutions,
|
|
|
|
|
string WorktreeStrategy,
|
|
|
|
|
string? CentralWorktreeRoot,
|
|
|
|
|
bool WorktreeAutoCleanupEnabled,
|
|
|
|
|
int WorktreeAutoCleanupDays,
|
|
|
|
|
string? ReportExcludedPaths,
|
|
|
|
|
int StandupWeekday,
|
|
|
|
|
int DailyPrepMaxTasks,
|
|
|
|
|
List<string>? SessionSkills = null,
|
|
|
|
|
List<ModelPresetDto>? ModelPresets = null,
|
|
|
|
|
int UsageGateFiveHourPct = 80,
|
|
|
|
|
int UsageGateSevenDayPct = 90,
|
|
|
|
|
int MaxTurnsCeiling = 80,
|
|
|
|
|
// Throttle stages per bucket — dragged on the usage-monitor gauges, not typed in Settings.
|
|
|
|
|
int UsageThrottleFiveHourSoftPct = 50,
|
|
|
|
|
int UsageThrottleFiveHourHardPct = 65,
|
|
|
|
|
int UsageThrottleSevenDaySoftPct = 50,
|
|
|
|
|
int UsageThrottleSevenDayHardPct = 65,
|
|
|
|
|
bool AutoContinueOnUsageLimit = false);
|
|
|
|
|
|
|
|
|
|
// Per-model run defaults (effort + turn budget) edited in Settings → General.
|
|
|
|
|
public sealed record ModelPresetDto(string Model, string Effort, int MaxTurns);
|
|
|
|
|
|
|
|
|
|
public sealed record SessionSkillDto(
|
|
|
|
|
string Name,
|
|
|
|
|
string Description,
|
|
|
|
|
string SourceUrl,
|
|
|
|
|
string PinnedRef,
|
|
|
|
|
DateTimeOffset AddedAt);
|
|
|
|
|
|
|
|
|
|
public sealed record WorktreeCleanupDto(int Removed);
|
|
|
|
|
public sealed record WorktreeResetDto(int Removed, int TasksAffected, bool Blocked, int RunningTasks);
|
|
|
|
|
public record MergeResultDto(string Status, IReadOnlyList<string> ConflictFiles, string? ErrorMessage);
|
|
|
|
|
public record BaseDirtyWarningDto(int ModifiedCount, int UntrackedCount);
|
|
|
|
|
public record SetTaskStatusResultDto(BaseDirtyWarningDto? BaseDirty);
|
|
|
|
|
public record MergePreviewDto(string Status, IReadOnlyList<string> ConflictFiles, int ChangedFileCount);
|
|
|
|
|
public record MergeTargetsDto(
|
|
|
|
|
string DefaultBranch, IReadOnlyList<string> LocalBranches, string DefaultCommitMessage);
|
|
|
|
|
public record MergeConflictDocumentsDto(string TaskId, IReadOnlyList<ConflictDocumentDto> Files);
|
|
|
|
|
public record ConflictDocumentDto(string Path, bool IsBinary, IReadOnlyList<MergeSegmentDto> Segments);
|
|
|
|
|
public record MergeSegmentDto(bool IsConflict, string Text, string Ours, string? Base, string Theirs);
|
|
|
|
|
public sealed record UpdateListDto(string Id, string Name, string? WorkingDir, string DefaultCommitType, bool IsManual = false, bool FindingsTracked = false);
|
|
|
|
|
public sealed record UpdateListConfigDto(string ListId, string? Model, string? SystemPrompt, string? AgentPath, int? MaxTurns = null, List<string>? SessionSkills = null, string? VerifyCommand = null);
|
|
|
|
|
public sealed record UpdateTaskAgentSettingsDto(string TaskId, string? Model, string? SystemPrompt, string? AgentPath, int? MaxTurns = null, List<string>? SessionSkills = null);
|
|
|
|
|
public sealed record ListConfigDto(string? Model, string? SystemPrompt, string? AgentPath, int? MaxTurns = null, List<string>? SessionSkills = null, string? VerifyCommand = null);
|
|
|
|
|
public sealed record SeedResultDto(int Copied, int Skipped);
|
|
|
|
|
|
|
|
|
|
public sealed record WorktreeOverviewDto(
|
|
|
|
|
string TaskId,
|
|
|
|
|
string TaskTitle,
|
|
|
|
|
ClaudeDo.Data.Models.TaskStatus TaskStatus,
|
|
|
|
|
string ListId,
|
|
|
|
|
string ListName,
|
|
|
|
|
string Path,
|
|
|
|
|
string BranchName,
|
|
|
|
|
string BaseCommit,
|
|
|
|
|
WorktreeState State,
|
|
|
|
|
string? DiffStat,
|
|
|
|
|
DateTime CreatedAt,
|
|
|
|
|
bool PathExistsOnDisk);
|
|
|
|
|
|
|
|
|
|
public sealed record LaunchSpec(
|
|
|
|
|
string Cwd,
|
|
|
|
|
string Exe,
|
|
|
|
|
IReadOnlyList<string> Args,
|
|
|
|
|
IReadOnlyDictionary<string, string> Env);
|
|
|
|
|
|
|
|
|
|
public sealed record ForceRemoveResultDto(bool Removed, string? Reason);
|
|
|
|
|
public sealed record PlanningMergeConflictStateDto(string PlanningTaskId, string SubtaskId);
|
|
|
|
|
public sealed record PendingQuestionDto(string TaskId, string QuestionId, string Question);
|
|
|
|
|
public sealed record WorkerBuildInfoDto(string? BuildSha);
|
|
|
|
|
|
|
|
|
|
public sealed record OnlineInboxStateDto(
|
|
|
|
|
bool Enabled,
|
|
|
|
|
string ApiBaseUrl,
|
|
|
|
|
string Authority,
|
|
|
|
|
string ClientId,
|
|
|
|
|
string Scopes,
|
|
|
|
|
string RedirectUri,
|
|
|
|
|
bool SignedIn,
|
|
|
|
|
int PollIntervalSeconds);
|
|
|
|
|
|
|
|
|
|
public sealed record OnlineInboxConfigInputDto(
|
|
|
|
|
bool Enabled,
|
|
|
|
|
string ApiBaseUrl,
|
|
|
|
|
int PollIntervalSeconds,
|
|
|
|
|
string Authority,
|
|
|
|
|
string ClientId,
|
|
|
|
|
string Scopes,
|
|
|
|
|
string RedirectUri);
|
|
|
|
|
|
|
|
|
|
public sealed record UsageLimitDto(
|
|
|
|
|
string Kind,
|
|
|
|
|
string Group,
|
|
|
|
|
double Percent,
|
|
|
|
|
string Severity,
|
|
|
|
|
DateTimeOffset? ResetsAt,
|
|
|
|
|
string? ScopeModelDisplayName,
|
|
|
|
|
bool IsActive);
|
|
|
|
|
|
|
|
|
|
public sealed record UsageSnapshotDto(
|
|
|
|
|
double? FiveHourPercent,
|
|
|
|
|
DateTimeOffset? FiveHourResetsAt,
|
|
|
|
|
double? SevenDayPercent,
|
|
|
|
|
DateTimeOffset? SevenDayResetsAt,
|
|
|
|
|
IReadOnlyList<UsageLimitDto> Limits,
|
|
|
|
|
int FiveHourThresholdPct,
|
|
|
|
|
int SevenDayThresholdPct,
|
|
|
|
|
bool IsGateBlocked,
|
|
|
|
|
string? GateReason,
|
|
|
|
|
DateTime? FetchedAtUtc,
|
|
|
|
|
bool IsStale,
|
|
|
|
|
string? LastError,
|
|
|
|
|
int ConfiguredSlots,
|
|
|
|
|
int EffectiveSlots,
|
|
|
|
|
string? ThrottleBucket,
|
|
|
|
|
// Throttle stages per bucket, drawn (and dragged) on the usage-monitor gauges. Defaults match
|
|
|
|
|
// the DB defaults so an older worker that doesn't send them yet still yields sane markers.
|
|
|
|
|
int ThrottleFiveHourSoftPct = 50,
|
|
|
|
|
int ThrottleFiveHourHardPct = 65,
|
|
|
|
|
int ThrottleSevenDaySoftPct = 50,
|
|
|
|
|
int ThrottleSevenDayHardPct = 65);
|
|
|
|
|
|
|
|
|
|
public sealed record ModelUsageRowDto(
|
|
|
|
|
DateOnly Date,
|
|
|
|
|
string Model,
|
|
|
|
|
string Scope,
|
|
|
|
|
long InputTokens,
|
|
|
|
|
long OutputTokens,
|
|
|
|
|
long CacheReadTokens,
|
|
|
|
|
long CacheCreationTokens,
|
|
|
|
|
int Messages,
|
|
|
|
|
double? CostUsd = null);
|
|
|
|
|
|
|
|
|
|
public sealed record TaskUsageRowDto(
|
|
|
|
|
string TaskId,
|
|
|
|
|
string TaskTitle,
|
|
|
|
|
string ListId,
|
|
|
|
|
string ListName,
|
|
|
|
|
string? Model,
|
|
|
|
|
int Runs,
|
|
|
|
|
long TokensIn,
|
|
|
|
|
long TokensOut,
|
|
|
|
|
double? CostUsd = null,
|
|
|
|
|
int? Retries = null,
|
|
|
|
|
bool? Productive = null,
|
|
|
|
|
bool? OneShot = null);
|
|
|
|
|
|
|
|
|
|
public sealed record TokenTrackerDashboardDto(bool Ok, string? Url, string? Error);
|
|
|
|
|
|
|
|
|
|
public sealed record TokenTrackerStatusDto(
|
|
|
|
|
bool Installed,
|
|
|
|
|
string? Version,
|
|
|
|
|
bool NodeOk,
|
|
|
|
|
string? NodeVersion,
|
|
|
|
|
DateTime? LastFetchedUtc,
|
|
|
|
|
string? LastError,
|
|
|
|
|
int? FormatVersion,
|
|
|
|
|
int SessionCount);
|
|
|
|
|