fix(ui): surface interactive/planning launch errors in footer

This commit is contained in:
Mika Kuns
2026-06-23 08:41:03 +02:00
parent 9301bbc81a
commit 134b9fb598
4 changed files with 33 additions and 4 deletions

View File

@@ -88,6 +88,14 @@
"inheritedFromGlobal": "geerbt · Global",
"overrideBadge": "überschrieben",
"resetToInherited": "Auf geerbt zurücksetzen"
},
"agentEditor": {
"model": "Modell",
"maxTurns": "Max. Durchläufe",
"systemPrompt": "System-Prompt (angehängt)",
"promptPrepended": "Wird automatisch vorangestellt:",
"agentFile": "Agent-Datei",
"browse": "Durchsuchen..."
}
},
"tasks": {
@@ -464,7 +472,7 @@
"taskStatus": { "idle": "Leerlauf", "queued": "In Warteschlange", "running": "Läuft", "waitingForReview": "Wartet auf Prüfung", "waitingForChildren": "Wartet auf Verbesserungen", "done": "Fertig", "failed": "Fehlgeschlagen", "cancelled": "Abgebrochen", "parked": "Geparkt" },
"planningBadge": { "active": "PLANUNG", "finalized": "GEPLANT" },
"taskRow": { "createdPrefix": "Erstellt {0}", "stepsText": "{0}/{1} Schritte" },
"tasksIsland": { "completedHeader": "ABGESCHLOSSEN", "completedHeaderCount": "ABGESCHLOSSEN · {0}" },
"tasksIsland": { "completedHeader": "ABGESCHLOSSEN", "completedHeaderCount": "ABGESCHLOSSEN · {0}", "runInteractiveFailed": "Interaktiv ausführen fehlgeschlagen: {0}", "planningOpenFailed": "Planungssitzung konnte nicht geöffnet werden: {0}" },
"diff": { "loadFailed": "Diff konnte nicht geladen werden: {0}", "noChanges": "Keine Änderungen anzuzeigen.", "unavailable": "Diff nicht mehr verfügbar — Commit-Bereich unvollständig." },
"planningDiff": { "hubError": "Kombinierte Vorschau konnte nicht erstellt werden (Hub-Fehler).", "conflict": "Kombinierte Vorschau nicht möglich: Teilaufgabe {0} steht im Konflikt mit einer früheren Teilaufgabe ({1} Dateien)." },
"merge": { "commitMessage": "Merge-Aufgabe: {0}", "workerOfflineBranches": "Worker offline — Branches können nicht aufgelistet werden.", "loadBranchesFailed": "Branches konnten nicht geladen werden: {0}", "merged": "Zusammengeführt.", "conflict": "Merge-Konflikt — Ziel-Branch wiederhergestellt. Manuell oder über Fortsetzen lösen, dann erneut versuchen.", "blocked": "Blockiert: {0}", "unknownStatus": "Unbekannter Status: {0}", "mergeFailed": "Merge fehlgeschlagen: {0}" },

View File

@@ -88,6 +88,14 @@
"inheritedFromGlobal": "inherited · Global",
"overrideBadge": "override",
"resetToInherited": "Reset to inherited"
},
"agentEditor": {
"model": "Model",
"maxTurns": "Max turns",
"systemPrompt": "System prompt (appended)",
"promptPrepended": "Prepended automatically:",
"agentFile": "Agent file",
"browse": "Browse..."
}
},
"tasks": {
@@ -464,7 +472,7 @@
"taskStatus": { "idle": "Idle", "queued": "Queued", "running": "Running", "waitingForReview": "Waiting for Review", "waitingForChildren": "Waiting for Improvements", "done": "Done", "failed": "Failed", "cancelled": "Cancelled", "parked": "Parked" },
"planningBadge": { "active": "PLANNING", "finalized": "PLANNED" },
"taskRow": { "createdPrefix": "Created {0}", "stepsText": "{0}/{1} steps" },
"tasksIsland": { "completedHeader": "COMPLETED", "completedHeaderCount": "COMPLETED · {0}" },
"tasksIsland": { "completedHeader": "COMPLETED", "completedHeaderCount": "COMPLETED · {0}", "runInteractiveFailed": "Run interactively failed: {0}", "planningOpenFailed": "Couldn't open planning session: {0}" },
"diff": { "loadFailed": "Failed to load diff: {0}", "noChanges": "No changes to show.", "unavailable": "Diff no longer available — commit range incomplete." },
"planningDiff": { "hubError": "Could not build combined preview (hub error).", "conflict": "Cannot build combined preview: subtask {0} conflicts with an earlier subtask ({1} files)." },
"merge": { "commitMessage": "Merge task: {0}", "workerOfflineBranches": "Worker offline — cannot list branches.", "loadBranchesFailed": "Failed to load branches: {0}", "merged": "Merged.", "conflict": "Merge conflict — target branch restored. Resolve manually or via Continue, then retry.", "blocked": "Blocked: {0}", "unknownStatus": "Unknown status: {0}", "mergeFailed": "Merge failed: {0}" },

View File

@@ -28,6 +28,7 @@ public sealed partial class TasksIslandViewModel : ViewModelBase, IDisposable
public event EventHandler? TasksChanged;
public event Action? NotesRequested;
public event Action? PrepRequested;
public event Action<string>? ErrorReported;
public void RequestFocusAddTask() => FocusAddTaskRequested?.Invoke(this, EventArgs.Empty);
[RelayCommand]
@@ -770,7 +771,7 @@ public sealed partial class TasksIslandViewModel : ViewModelBase, IDisposable
if (row.Status != TaskStatus.Idle || row.PlanningPhase != PlanningPhase.None) return;
ForegroundHelper.AllowAny();
try { await _worker!.StartPlanningSessionAsync(row.Id); }
catch { }
catch (Exception ex) { ErrorReported?.Invoke(Loc.T("vm.tasksIsland.planningOpenFailed", ex.Message)); }
}
[RelayCommand]
@@ -779,7 +780,7 @@ public sealed partial class TasksIslandViewModel : ViewModelBase, IDisposable
if (row is null || _worker is null) return;
ForegroundHelper.AllowAny();
try { await _worker.OpenInteractiveTerminalAsync(row.Id); }
catch { }
catch (Exception ex) { ErrorReported?.Invoke(Loc.T("vm.tasksIsland.runInteractiveFailed", ex.Message)); }
}
[RelayCommand]

View File

@@ -125,6 +125,17 @@ public sealed partial class IslandsShellViewModel : ViewModelBase, IDisposable
WorkerLogText = null;
}
// Surfaces a UI-originated failure in the footer status strip (same line as the
// worker log), color-coded as an error and auto-cleared by _clearTimer.
public void FlashFooterError(string message)
{
WorkerLogText = $"{DateTime.Now:HH:mm} · {message}";
WorkerLogLevel = WorkerLogLevel.Error;
IsWorkerLogVisible = true;
_clearTimer.Stop();
_clearTimer.Start();
}
private void OnPrimeFired(PrimeFiredEvent evt)
{
var when = evt.FiredAt.LocalDateTime.ToString("HH:mm");
@@ -181,6 +192,7 @@ public sealed partial class IslandsShellViewModel : ViewModelBase, IDisposable
Tasks.SelectionChanged += (_, _) => Details.Bind(Tasks.SelectedTask);
Tasks.NotesRequested += () => Details.ShowNotes();
Tasks.PrepRequested += () => Details.ShowPrep();
Tasks.ErrorReported += FlashFooterError;
Tasks.TasksChanged += (_, _) => _ = Lists.RefreshCountsAsync();
Tasks.OpenListSettingsRequested += (_, _) =>
{