Merge claudedo/3832008a0b5147bf8308407ed4bd1ded

This commit is contained in:
mika kuns
2026-07-29 13:26:15 +02:00
14 changed files with 284 additions and 25 deletions
+14 -14
View File
@@ -329,8 +329,8 @@ public partial class WorkerClient : ObservableObject, IAsyncDisposable, IWorkerC
await _hub.InvokeAsync("RefreshAgents");
}
public Task<SeedResultDto?> RestoreDefaultAgentsAsync()
=> TryInvokeAsync<SeedResultDto>("RestoreDefaultAgents");
public async Task<SeedResultDto?> RestoreDefaultAgentsAsync()
=> await _hub.InvokeAsync<SeedResultDto>("RestoreDefaultAgents");
private async Task SeedActiveTasksAsync()
{
@@ -372,8 +372,8 @@ public partial class WorkerClient : ObservableObject, IAsyncDisposable, IWorkerC
public async Task<List<PrimeScheduleDto>> GetPrimeSchedulesAsync()
=> await TryInvokeAsync<List<PrimeScheduleDto>>("ListPrimeSchedules") ?? new List<PrimeScheduleDto>();
public Task<PrimeScheduleDto?> UpsertPrimeScheduleAsync(PrimeScheduleDto dto)
=> TryInvokeAsync<PrimeScheduleDto>("UpsertPrimeSchedule", dto);
public async Task<PrimeScheduleDto?> UpsertPrimeScheduleAsync(PrimeScheduleDto dto)
=> await _hub.InvokeAsync<PrimeScheduleDto>("UpsertPrimeSchedule", dto);
public async Task DeletePrimeScheduleAsync(Guid id)
{
@@ -400,8 +400,8 @@ public partial class WorkerClient : ObservableObject, IAsyncDisposable, IWorkerC
public async Task<List<DailyNoteDto>> GetDailyNotesAsync(DateOnly day)
=> await TryInvokeAsync<List<DailyNoteDto>>("GetDailyNotes", IsoDay(day)) ?? new List<DailyNoteDto>();
public Task<DailyNoteDto?> AddDailyNoteAsync(DateOnly day, string text)
=> TryInvokeAsync<DailyNoteDto>("AddDailyNote", IsoDay(day), text);
public async Task<DailyNoteDto?> AddDailyNoteAsync(DateOnly day, string text)
=> await _hub.InvokeAsync<DailyNoteDto>("AddDailyNote", IsoDay(day), text);
public async Task UpdateDailyNoteAsync(string id, string text)
=> await _hub.InvokeAsync("UpdateDailyNote", id, text);
@@ -474,11 +474,11 @@ public partial class WorkerClient : ObservableObject, IAsyncDisposable, IWorkerC
await _hub.InvokeAsync("CancelReview", taskId);
}
public Task<WorktreeCleanupDto?> CleanupFinishedWorktreesAsync(string? listId = null)
=> TryInvokeAsync<WorktreeCleanupDto>("CleanupFinishedWorktrees", listId);
public async Task<WorktreeCleanupDto?> CleanupFinishedWorktreesAsync(string? listId = null)
=> await _hub.InvokeAsync<WorktreeCleanupDto>("CleanupFinishedWorktrees", listId);
public Task<WorktreeResetDto?> ResetAllWorktreesAsync()
=> TryInvokeAsync<WorktreeResetDto>("ResetAllWorktrees");
public async Task<WorktreeResetDto?> ResetAllWorktreesAsync()
=> await _hub.InvokeAsync<WorktreeResetDto>("ResetAllWorktrees");
public async Task<List<WorktreeOverviewDto>> GetWorktreesOverviewAsync(string? listId)
=> await TryInvokeAsync<List<WorktreeOverviewDto>>("GetWorktreesOverview", listId)
@@ -501,8 +501,8 @@ public partial class WorkerClient : ObservableObject, IAsyncDisposable, IWorkerC
}
}
public Task<ForceRemoveResultDto?> ForceRemoveWorktreeAsync(string taskId)
=> TryInvokeAsync<ForceRemoveResultDto>("ForceRemoveWorktree", taskId);
public async Task<ForceRemoveResultDto?> ForceRemoveWorktreeAsync(string taskId)
=> await _hub.InvokeAsync<ForceRemoveResultDto>("ForceRemoveWorktree", taskId);
public async Task<PlanningSessionStartInfo> StartPlanningSessionAsync(string taskId, CancellationToken ct = default)
=> await _hub.InvokeAsync<PlanningSessionStartInfo>("StartPlanningSessionAsync", taskId, ct);
@@ -543,8 +543,8 @@ public partial class WorkerClient : ObservableObject, IAsyncDisposable, IWorkerC
public async Task<IReadOnlyList<SubtaskDiffDto>> GetPlanningAggregateAsync(string planningTaskId)
=> await TryInvokeAsync<List<SubtaskDiffDto>>("GetPlanningAggregate", planningTaskId) ?? [];
public Task<CombinedDiffResultDto?> BuildPlanningIntegrationBranchAsync(string planningTaskId, string targetBranch)
=> TryInvokeAsync<CombinedDiffResultDto>("BuildPlanningIntegrationBranch", planningTaskId, targetBranch);
public async Task<CombinedDiffResultDto?> BuildPlanningIntegrationBranchAsync(string planningTaskId, string targetBranch)
=> await _hub.InvokeAsync<CombinedDiffResultDto>("BuildPlanningIntegrationBranch", planningTaskId, targetBranch);
public async Task ContinuePlanningMergeAsync(string planningTaskId)
{
@@ -311,6 +311,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
Prep = new PrepPanelViewModel(worker);
Notes = new NotesEditorViewModel(_notesApi);
Notes.ErrorReported += msg => { if (ShowErrorAsync is not null) _ = ShowErrorAsync(msg); };
Subtasks.CollectionChanged += (_, _) => NotifyStepsChanged();
Subtasks.CollectionChanged += (_, _) => Merge.SyncChildOutcomes(HasChildOutcomes, Subtasks.Count);
Attachments.CollectionChanged += (_, _) => OnPropertyChanged(nameof(FilesBadge));
@@ -24,6 +24,9 @@ public sealed partial class NotesEditorViewModel : ViewModelBase
public NotesEditorViewModel(INotesApi api) => _api = api;
// Raised when a worker call fails so the host VM can surface it (e.g. via ShowErrorAsync).
public event Action<string>? ErrorReported;
public ObservableCollection<NoteBulletViewModel> Bullets { get; } = new();
[ObservableProperty] private DateOnly _currentDay = DateOnly.FromDateTime(DateTime.Today);
@@ -55,9 +58,16 @@ public sealed partial class NotesEditorViewModel : ViewModelBase
{
var text = NewBulletText.Trim();
if (text.Length == 0) return;
var dto = await _api.AddAsync(CurrentDay, text);
if (dto is not null) Bullets.Add(MakeBullet(dto.Id, dto.Text));
NewBulletText = "";
try
{
var dto = await _api.AddAsync(CurrentDay, text);
if (dto is not null) Bullets.Add(MakeBullet(dto.Id, dto.Text));
NewBulletText = "";
}
catch (Exception ex)
{
ErrorReported?.Invoke(ex.Message);
}
}
[RelayCommand] private Task PrevDay() => LoadDayAsync(CurrentDay.AddDays(-1));
@@ -197,6 +197,11 @@ public sealed partial class DiffViewerViewModel : ViewModelBase
DisplayedDiff = "";
}
}
catch (Exception ex)
{
DisplayedDiff = "";
CombinedWarning = Loc.T("vm.planningDiff.buildFailed", ex.Message);
}
finally
{
IsLoadingCombined = false;
@@ -46,6 +46,7 @@ public sealed partial class WorktreesSettingsTabViewModel : ViewModelBase
var r = await _worker.CleanupFinishedWorktreesAsync();
StatusMessage = r is null ? Loc.T("vm.worktreesTab.workerOffline") : Loc.T("vm.worktreesTab.removed", r.Removed);
}
catch (Exception ex) { StatusMessage = Loc.T("vm.worktreesTab.cleanupFailed", ex.Message); }
finally { IsBusy = false; }
}
@@ -63,6 +64,7 @@ public sealed partial class WorktreesSettingsTabViewModel : ViewModelBase
else if (r.Blocked) StatusMessage = Loc.T("vm.worktreesTab.blocked", r.RunningTasks);
else StatusMessage = Loc.T("vm.worktreesTab.removedFrom", r.Removed, r.TasksAffected);
}
catch (Exception ex) { StatusMessage = Loc.T("vm.worktreesTab.resetFailed", ex.Message); }
finally { IsBusy = false; }
}
}
@@ -174,6 +174,7 @@ public sealed partial class WorktreesOverviewModalViewModel : ViewModelBase
StatusMessage = result is null ? Loc.T("vm.worktreesOverview.cleanupFailed") : Loc.T("vm.worktreesOverview.removed", result.Removed);
await LoadAsync();
}
catch (Exception ex) { StatusMessage = Loc.T("vm.worktreesOverview.cleanupFailedDetailed", ex.Message); }
finally { IsBusy = false; }
}
@@ -241,7 +242,16 @@ public sealed partial class WorktreesOverviewModalViewModel : ViewModelBase
if (row.IsRunning) { StatusMessage = Loc.T("vm.worktreesOverview.cannotForceRunning"); return; }
if (ConfirmAction is not null && !await ConfirmAction($"Force remove worktree for '{row.TaskTitle}'? This deletes the directory and branch.")) return;
var result = await _worker.ForceRemoveWorktreeAsync(row.TaskId);
ForceRemoveResultDto? result;
try
{
result = await _worker.ForceRemoveWorktreeAsync(row.TaskId);
}
catch (Exception ex)
{
StatusMessage = Loc.T("vm.worktreesOverview.forceRemoveFailedDetailed", ex.Message);
return;
}
if (result is null || !result.Removed)
{
StatusMessage = result?.Reason ?? Loc.T("vm.worktreesOverview.forceRemoveFailed");