UI-Entwurf umgesetzt, Rocket.Chat-Tool, Deploymentcenter 2.4

Sicherungspunkt vor dem Aufraeumen. Buendelt die Arbeit, die seit dem
Abschluss der Avalonia-Portierung im Arbeitsverzeichnis lag.

Oberflaeche
- Entwurf aus Mockup/ umgesetzt: Theme.axaml (Farben je Thema, Barlow als
  mitgelieferte Schrift), Icons.axaml (Symbolgeometrien), Shell.axaml
  (eigene ControlThemes statt Fluent umzufaerben).
- Neue Steuerelemente StrokeIcon und BlueprintFrame, Seiten fuer
  Token-Verbrauch und Agenten-Chats, Werkzeug-Einstellungen als Seite
  statt eigenem Fenster, Texteditor-Fenster.
- ThemeManager mit hellem und dunklem Thema; die beiden Pinsel-Konverter
  entfallen, weil ein fester Farbwert den Themenwechsel nicht ueberlebt.

Rocket.Chat
- Neues Tool-Projekt (Client, Konfiguration, Workspace-Dateien) nach der
  Bauform des Telegram-Tools: rocketchat_poll als Tool-Job, geweckt wird
  nur, wenn wirklich etwas anliegt.
- send_file ist freigabepflichtig, send_message bewusst nicht: Der Raum
  ist Arbeitsraum, der Schutz sitzt an der Raum-Allowlist.
- Konzept-Doc um die Messung gegen die echte Instanz 8.7 ergaenzt; drei
  Annahmen waren falsch und sind korrigiert.

Deploymentcenter
- DC6 (Update anwenden) und DC7 (Erstinstallation ueber setup.json)
  erledigt, DC3 fuer win-x64/dev; deploy/publish.py als Release-Strecke.
- AppHost.DisposeAsync gegen doppeltes Herunterfahren gesperrt - sonst
  ueberschreibt eine zweite Abmeldung den Wartungszustand am Watchdog.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-08-23 12:16:05 +02:00
co-authored by Claude Opus 5
parent b5bf97ae74
commit 33d95a6c3f
88 changed files with 11665 additions and 1029 deletions
@@ -25,6 +25,10 @@ public sealed class WatchdogHeartbeatService : IAsyncDisposable
private Task? _loop;
private string _lastState = "unknown";
private string _shutdownStatus = WatchdogStatus.Stopped;
private string _shutdownMessage = "Instanz planmäßig beendet.";
private string _shutdownEventKind = WatchdogEventKind.StoppedGraceful;
public WatchdogHeartbeatService(
IWatchdogClient client,
IInstanceHealthProvider health,
@@ -57,6 +61,23 @@ public sealed class WatchdogHeartbeatService : IAsyncDisposable
/// <summary>Der zuletzt vom Server gemeldete Monitor-Zustand — für die Anzeige.</summary>
public string LastState => _lastState;
/// <summary>
/// Meldet das nächste Herunterfahren als <b>Wartung</b> statt als planmäßiges Ende.
///
/// <para>Gedacht für das Einspielen eines Updates: Die Instanz ist gleich weg,
/// kommt aber wieder. <c>stopped</c> wäre die falsche Auskunft — es heißt „bewusst
/// beendet" und lässt den Monitor liegen, bis jemand ihn wieder anfasst.
/// <c>maintenance</c> sagt dasselbe über den Alarm aus, trägt aber die Absicht
/// mit: Im Dashboard ist zu sehen, dass hier gerade aktualisiert wird, statt dass
/// eine Instanz ohne Grund verschwindet.</para>
/// </summary>
public void AnnounceMaintenance(string message)
{
_shutdownStatus = WatchdogStatus.Maintenance;
_shutdownMessage = message;
_shutdownEventKind = WatchdogEventKind.MaintenanceStart;
}
public void Start()
{
if (IsRunning)
@@ -176,12 +197,12 @@ public sealed class WatchdogHeartbeatService : IAsyncDisposable
await _client.SendHeartbeatAsync(
new InstanceHealth(
WatchdogStatus.Stopped, "Instanz planmäßig beendet.",
_shutdownStatus, _shutdownMessage,
new Dictionary<string, double>(), new Dictionary<string, HealthCheck>()),
_intervalSeconds, stopCts.Token).ConfigureAwait(false);
await _client.SendEventAsync(
WatchdogEventKind.StoppedGraceful, "info", "Instanz beendet.", null, stopCts.Token)
_shutdownEventKind, "info", _shutdownMessage, null, stopCts.Token)
.ConfigureAwait(false);
}
catch (Exception ex)