From 6d81693041d1fdc8c7a5f37b168f79ad6011bc15 Mon Sep 17 00:00:00 2001 From: Richard Date: Fri, 2 Oct 2026 20:23:12 +0200 Subject: [PATCH] Stufe 3 (#764): Avalonia-Fenster entfernt - Views, ViewModels, Controls, Converters, Styles, Services, Desktop-i18n, Schriften und App.axaml raus; Avalonia- und Mvvm-Pakete raus - ClawdDotNet ohne Schalter: Manager starten (unter systemd ueber den Dienst, nie doppelt) und WebUI oeffnen (LauncherRun) - bis die Huelle kommt - Instanzen laufen immer kopflos; instanceWindows wird gelesen, nicht mehr ausgewertet; die Kette 'Fenster nach vorn holen' ist entfernt - Telegram-Anmeldung nur noch ueber die WebUI (tote Dialog-Rueckrufe raus) - systemd-Vorlagen im Linux-Paket; Oberflaechen-Leitfaden ins Archiv Co-Authored-By: Claude Opus 5.5 --- CLAUDE.md | 2 +- deploy/publish.py | 9 + docs/Roadmap.md | 4 +- docs/WebUI-Leitfaden.md | 2 +- docs/{ => archiv}/Oberflaechen-Leitfaden.md | 4 + .../WebUI-Only-und-Englisch.md | 13 + src/ClawdDotNet.App/AppHost.cs | 51 +- src/ClawdDotNet.Desktop/App.axaml | 16 - src/ClawdDotNet.Desktop/App.axaml.cs | 995 ------------------ .../Assets/Fonts/Barlow-Bold.ttf | Bin 108220 -> 0 bytes .../Assets/Fonts/Barlow-Medium.ttf | Bin 103536 -> 0 bytes .../Assets/Fonts/Barlow-Regular.ttf | Bin 104068 -> 0 bytes .../Assets/Fonts/Barlow-SemiBold.ttf | Bin 108348 -> 0 bytes .../Assets/Fonts/BarlowCondensed-Medium.ttf | Bin 103360 -> 0 bytes .../Assets/Fonts/BarlowCondensed-Regular.ttf | Bin 102480 -> 0 bytes .../Assets/Fonts/BarlowCondensed-SemiBold.ttf | Bin 109428 -> 0 bytes src/ClawdDotNet.Desktop/Assets/Fonts/OFL.txt | 93 -- .../ClawdDotNet.Desktop.csproj | 38 +- .../Controls/BlueprintFrame.cs | 24 - .../Controls/StrokeIcon.cs | 113 -- .../Converters/IconConverter.cs | 54 - .../Converters/LayoutConverters.cs | 40 - .../Converters/StringEqualsConverter.cs | 27 - src/ClawdDotNet.Desktop/LauncherRun.cs | 180 ++++ src/ClawdDotNet.Desktop/Program.cs | 40 +- .../Services/AvaloniaLicensePrompt.cs | 86 -- .../Services/LocalizationManager.cs | 199 ---- .../Services/LocalizeExtension.cs | 30 - .../Services/ThemeManager.cs | 35 - src/ClawdDotNet.Desktop/Styles/Icons.axaml | 51 - src/ClawdDotNet.Desktop/Styles/Shell.axaml | 862 --------------- src/ClawdDotNet.Desktop/Styles/Theme.axaml | 174 --- src/ClawdDotNet.Desktop/ViewLocator.cs | 40 - .../ViewModels/AddAgentViewModel.cs | 76 -- .../ViewModels/AddJobViewModel.cs | 111 -- .../ViewModels/AddServiceViewModel.cs | 67 -- .../ViewModels/AgentChatsPageViewModel.cs | 93 -- .../ViewModels/AgentsPageViewModel.cs | 531 ---------- .../ViewModels/BackupPageViewModel.cs | 415 -------- .../ViewModels/ChatPageViewModel.cs | 158 --- .../ViewModels/InfoPageViewModel.cs | 102 -- .../ViewModels/InstancePickerViewModel.cs | 190 ---- .../ViewModels/LicenseViewModel.cs | 46 - .../ViewModels/LogPageViewModel.cs | 116 -- .../ViewModels/MainWindowViewModel.cs | 396 ------- .../ViewModels/RestoreBackupViewModel.cs | 82 -- .../ViewModels/SettingsPageViewModel.cs | 227 ---- .../ViewModels/TasksPageViewModel.cs | 398 ------- .../ViewModels/TokenUsagePageViewModel.cs | 201 ---- .../ViewModels/ToolSettingsViewModel.cs | 221 ---- .../ViewModels/ViewModelBase.cs | 22 - .../Views/AddAgentWindow.axaml | 51 - .../Views/AddAgentWindow.axaml.cs | 21 - .../Views/AddJobWindow.axaml | 80 -- .../Views/AddJobWindow.axaml.cs | 21 - .../Views/AddServiceWindow.axaml | 53 - .../Views/AddServiceWindow.axaml.cs | 21 - .../Views/AgentChatsPageView.axaml | 61 -- .../Views/AgentChatsPageView.axaml.cs | 8 - .../Views/AgentsPageView.axaml | 293 ------ .../Views/AgentsPageView.axaml.cs | 101 -- .../Views/BackupPageView.axaml | 156 --- .../Views/BackupPageView.axaml.cs | 56 - .../Views/ChatPageView.axaml | 94 -- .../Views/ChatPageView.axaml.cs | 25 - .../Views/InfoPageView.axaml | 128 --- .../Views/InfoPageView.axaml.cs | 11 - .../Views/InstancePickerWindow.axaml | 123 --- .../Views/InstancePickerWindow.axaml.cs | 30 - .../Views/LicenseWindow.axaml | 45 - .../Views/LicenseWindow.axaml.cs | 16 - .../Views/LogPageView.axaml | 96 -- .../Views/LogPageView.axaml.cs | 21 - .../Views/MainWindow.axaml | 231 ---- .../Views/MainWindow.axaml.cs | 168 --- .../Views/RestoreBackupWindow.axaml | 66 -- .../Views/RestoreBackupWindow.axaml.cs | 42 - .../Views/SettingsPageView.axaml | 155 --- .../Views/SettingsPageView.axaml.cs | 11 - .../Views/TasksPageView.axaml | 257 ----- .../Views/TasksPageView.axaml.cs | 46 - .../Views/TextEditorWindow.axaml | 35 - .../Views/TextEditorWindow.axaml.cs | 51 - .../Views/TokenUsagePageView.axaml | 114 -- .../Views/TokenUsagePageView.axaml.cs | 8 - .../Views/ToolSettingsView.axaml | 239 ----- .../Views/ToolSettingsView.axaml.cs | 8 - src/ClawdDotNet.Desktop/i18n/de.json | 341 ------ src/ClawdDotNet.Desktop/i18n/en.json | 341 ------ src/ClawdDotNet.Manager.Web/Endpoints.cs | 19 - .../wwwroot/i18n/de.json | 1 - .../wwwroot/i18n/en.json | 1 - .../wwwroot/views/instances.js | 25 +- src/ClawdDotNet.Manager/InstanceChannel.cs | 12 - src/ClawdDotNet.Manager/InstanceLauncher.cs | 7 +- src/ClawdDotNet.Manager/InstanceRegistry.cs | 22 - src/ClawdDotNet.Manager/ManagerCore.cs | 3 - src/ClawdDotNet.Manager/ManagerSettings.cs | 5 + src/ClawdDotNet.ManagerApp/Program.cs | 5 +- .../Endpoints/ControlEndpoints.cs | 33 +- src/ClawdDotNet.Web/InstanceHttpHost.cs | 4 +- tests/ClawdDotNet.Manager.Tests/Doubles.cs | 12 - .../ManagerCoreTests.cs | 95 -- .../InstanceSocketTests.cs | 26 +- 104 files changed, 266 insertions(+), 10262 deletions(-) rename docs/{ => archiv}/Oberflaechen-Leitfaden.md (97%) delete mode 100644 src/ClawdDotNet.Desktop/App.axaml delete mode 100644 src/ClawdDotNet.Desktop/App.axaml.cs delete mode 100644 src/ClawdDotNet.Desktop/Assets/Fonts/Barlow-Bold.ttf delete mode 100644 src/ClawdDotNet.Desktop/Assets/Fonts/Barlow-Medium.ttf delete mode 100644 src/ClawdDotNet.Desktop/Assets/Fonts/Barlow-Regular.ttf delete mode 100644 src/ClawdDotNet.Desktop/Assets/Fonts/Barlow-SemiBold.ttf delete mode 100644 src/ClawdDotNet.Desktop/Assets/Fonts/BarlowCondensed-Medium.ttf delete mode 100644 src/ClawdDotNet.Desktop/Assets/Fonts/BarlowCondensed-Regular.ttf delete mode 100644 src/ClawdDotNet.Desktop/Assets/Fonts/BarlowCondensed-SemiBold.ttf delete mode 100644 src/ClawdDotNet.Desktop/Assets/Fonts/OFL.txt delete mode 100644 src/ClawdDotNet.Desktop/Controls/BlueprintFrame.cs delete mode 100644 src/ClawdDotNet.Desktop/Controls/StrokeIcon.cs delete mode 100644 src/ClawdDotNet.Desktop/Converters/IconConverter.cs delete mode 100644 src/ClawdDotNet.Desktop/Converters/LayoutConverters.cs delete mode 100644 src/ClawdDotNet.Desktop/Converters/StringEqualsConverter.cs create mode 100644 src/ClawdDotNet.Desktop/LauncherRun.cs delete mode 100644 src/ClawdDotNet.Desktop/Services/AvaloniaLicensePrompt.cs delete mode 100644 src/ClawdDotNet.Desktop/Services/LocalizationManager.cs delete mode 100644 src/ClawdDotNet.Desktop/Services/LocalizeExtension.cs delete mode 100644 src/ClawdDotNet.Desktop/Services/ThemeManager.cs delete mode 100644 src/ClawdDotNet.Desktop/Styles/Icons.axaml delete mode 100644 src/ClawdDotNet.Desktop/Styles/Shell.axaml delete mode 100644 src/ClawdDotNet.Desktop/Styles/Theme.axaml delete mode 100644 src/ClawdDotNet.Desktop/ViewLocator.cs delete mode 100644 src/ClawdDotNet.Desktop/ViewModels/AddAgentViewModel.cs delete mode 100644 src/ClawdDotNet.Desktop/ViewModels/AddJobViewModel.cs delete mode 100644 src/ClawdDotNet.Desktop/ViewModels/AddServiceViewModel.cs delete mode 100644 src/ClawdDotNet.Desktop/ViewModels/AgentChatsPageViewModel.cs delete mode 100644 src/ClawdDotNet.Desktop/ViewModels/AgentsPageViewModel.cs delete mode 100644 src/ClawdDotNet.Desktop/ViewModels/BackupPageViewModel.cs delete mode 100644 src/ClawdDotNet.Desktop/ViewModels/ChatPageViewModel.cs delete mode 100644 src/ClawdDotNet.Desktop/ViewModels/InfoPageViewModel.cs delete mode 100644 src/ClawdDotNet.Desktop/ViewModels/InstancePickerViewModel.cs delete mode 100644 src/ClawdDotNet.Desktop/ViewModels/LicenseViewModel.cs delete mode 100644 src/ClawdDotNet.Desktop/ViewModels/LogPageViewModel.cs delete mode 100644 src/ClawdDotNet.Desktop/ViewModels/MainWindowViewModel.cs delete mode 100644 src/ClawdDotNet.Desktop/ViewModels/RestoreBackupViewModel.cs delete mode 100644 src/ClawdDotNet.Desktop/ViewModels/SettingsPageViewModel.cs delete mode 100644 src/ClawdDotNet.Desktop/ViewModels/TasksPageViewModel.cs delete mode 100644 src/ClawdDotNet.Desktop/ViewModels/TokenUsagePageViewModel.cs delete mode 100644 src/ClawdDotNet.Desktop/ViewModels/ToolSettingsViewModel.cs delete mode 100644 src/ClawdDotNet.Desktop/ViewModels/ViewModelBase.cs delete mode 100644 src/ClawdDotNet.Desktop/Views/AddAgentWindow.axaml delete mode 100644 src/ClawdDotNet.Desktop/Views/AddAgentWindow.axaml.cs delete mode 100644 src/ClawdDotNet.Desktop/Views/AddJobWindow.axaml delete mode 100644 src/ClawdDotNet.Desktop/Views/AddJobWindow.axaml.cs delete mode 100644 src/ClawdDotNet.Desktop/Views/AddServiceWindow.axaml delete mode 100644 src/ClawdDotNet.Desktop/Views/AddServiceWindow.axaml.cs delete mode 100644 src/ClawdDotNet.Desktop/Views/AgentChatsPageView.axaml delete mode 100644 src/ClawdDotNet.Desktop/Views/AgentChatsPageView.axaml.cs delete mode 100644 src/ClawdDotNet.Desktop/Views/AgentsPageView.axaml delete mode 100644 src/ClawdDotNet.Desktop/Views/AgentsPageView.axaml.cs delete mode 100644 src/ClawdDotNet.Desktop/Views/BackupPageView.axaml delete mode 100644 src/ClawdDotNet.Desktop/Views/BackupPageView.axaml.cs delete mode 100644 src/ClawdDotNet.Desktop/Views/ChatPageView.axaml delete mode 100644 src/ClawdDotNet.Desktop/Views/ChatPageView.axaml.cs delete mode 100644 src/ClawdDotNet.Desktop/Views/InfoPageView.axaml delete mode 100644 src/ClawdDotNet.Desktop/Views/InfoPageView.axaml.cs delete mode 100644 src/ClawdDotNet.Desktop/Views/InstancePickerWindow.axaml delete mode 100644 src/ClawdDotNet.Desktop/Views/InstancePickerWindow.axaml.cs delete mode 100644 src/ClawdDotNet.Desktop/Views/LicenseWindow.axaml delete mode 100644 src/ClawdDotNet.Desktop/Views/LicenseWindow.axaml.cs delete mode 100644 src/ClawdDotNet.Desktop/Views/LogPageView.axaml delete mode 100644 src/ClawdDotNet.Desktop/Views/LogPageView.axaml.cs delete mode 100644 src/ClawdDotNet.Desktop/Views/MainWindow.axaml delete mode 100644 src/ClawdDotNet.Desktop/Views/MainWindow.axaml.cs delete mode 100644 src/ClawdDotNet.Desktop/Views/RestoreBackupWindow.axaml delete mode 100644 src/ClawdDotNet.Desktop/Views/RestoreBackupWindow.axaml.cs delete mode 100644 src/ClawdDotNet.Desktop/Views/SettingsPageView.axaml delete mode 100644 src/ClawdDotNet.Desktop/Views/SettingsPageView.axaml.cs delete mode 100644 src/ClawdDotNet.Desktop/Views/TasksPageView.axaml delete mode 100644 src/ClawdDotNet.Desktop/Views/TasksPageView.axaml.cs delete mode 100644 src/ClawdDotNet.Desktop/Views/TextEditorWindow.axaml delete mode 100644 src/ClawdDotNet.Desktop/Views/TextEditorWindow.axaml.cs delete mode 100644 src/ClawdDotNet.Desktop/Views/TokenUsagePageView.axaml delete mode 100644 src/ClawdDotNet.Desktop/Views/TokenUsagePageView.axaml.cs delete mode 100644 src/ClawdDotNet.Desktop/Views/ToolSettingsView.axaml delete mode 100644 src/ClawdDotNet.Desktop/Views/ToolSettingsView.axaml.cs delete mode 100644 src/ClawdDotNet.Desktop/i18n/de.json delete mode 100644 src/ClawdDotNet.Desktop/i18n/en.json diff --git a/CLAUDE.md b/CLAUDE.md index 48ad4b8..2311621 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -153,7 +153,7 @@ Umstellung des Bestands ist ein eigenes Vorhaben mit niedriger Priorität. | Dokument | Wofür | |---|---| -| [docs/Oberflaechen-Leitfaden.md](docs/Oberflaechen-Leitfaden.md) | **Eingefroren seit 2026-10-02:** Die Avalonia-Oberfläche wird nicht mehr gepflegt und zur Hülle um die WebUI umgebaut (#764). Neue Funktionen nur in API + WebUI | +| [docs/archiv/Oberflaechen-Leitfaden.md](docs/archiv/Oberflaechen-Leitfaden.md) | **Archiv:** Die Avalonia-Fenster sind mit #764 (Stufe 3) entfernt. `ClawdDotNet` ist Instanzprozess, MCP-Brücke und Starter; einzige Oberfläche ist die WebUI. Neue Funktionen nur in API + WebUI | | [docs/umsetzungsplaene/WebUI-Only-und-Englisch.md](docs/umsetzungsplaene/WebUI-Only-und-Englisch.md) | Der Umbau zur reinen WebUI und die Englisch-Komplettierung (#764) | | [docs/WebUI-Leitfaden.md](docs/WebUI-Leitfaden.md) | Arbeiten an der Weboberfläche (`ClawdDotNet.Web`, #494) — Schichtschnitt, API-Fläche, Sicherheitsvorgaben | | [docs/ToolDevelopmentGuide.md](docs/ToolDevelopmentGuide.md) | Ein neues Agenten-Tool bauen | diff --git a/deploy/publish.py b/deploy/publish.py index 944b8ba..da490d4 100644 --- a/deploy/publish.py +++ b/deploy/publish.py @@ -90,6 +90,15 @@ def publish(rid: str, out_dir: Path) -> None: ]) merge_manager(manager_dir, out_dir) + # #795: Die systemd-Vorlagen gehoeren ins Linux-Paket - sonst steht die Anleitung in + # einem Repository, das auf der Zielmaschine niemand hat. + if rid.startswith("linux"): + units = out_dir / "systemd" + units.mkdir(exist_ok=True) + for unit in sorted((REPO / "deploy" / "systemd").glob("*.service")): + shutil.copy2(unit, units / unit.name) + print(f" systemd-Vorlagen: {len(list(units.glob('*.service')))} nach systemd/") + def merge_manager(src: Path, dst: Path) -> None: """Legt den Manager neben die Instanz. diff --git a/docs/Roadmap.md b/docs/Roadmap.md index c7558f3..9bf2ae2 100644 --- a/docs/Roadmap.md +++ b/docs/Roadmap.md @@ -406,7 +406,7 @@ Anwendung stattdessen in ihr eigenes Installationsverzeichnis — das ein Update überschreibt. Der Befund blockiert damit denselben Betrieb, für den #214 und #215 da sind, und muss vor ihnen weg. -Die Pflichtliste des [Oberflächen-Leitfadens](Oberflaechen-Leitfaden.md) führt genau +Die Pflichtliste des [Oberflächen-Leitfadens](archiv/Oberflaechen-Leitfaden.md) führt genau diesen Fall: „Keine relativen Pfade … zeigt unter Linux ins Leere." Vorgabe für die Umsetzung: Ein relativer Wert wird gegen `instance.WorkingDirectory` @@ -885,7 +885,7 @@ Wer einen Punkt anfasst, liest das zugehörige Dokument zuerst. | Dokument | Wofür | |---|---| -| [Oberflaechen-Leitfaden](Oberflaechen-Leitfaden.md) | Arbeiten an `ClawdDotNet.Desktop`: Schichtschnitt, Fäden, Avalonia-12-Fallen, Prüfliste. Die Oberfläche hat **keine** Testabdeckung — Abschnitt 4 ist deshalb Pflichtlektüre vor jeder Abgabe | +| [Oberflaechen-Leitfaden](archiv/Oberflaechen-Leitfaden.md) | **Archiv seit #764** (Fenster entfernt). Damals: Arbeiten an `ClawdDotNet.Desktop`: Schichtschnitt, Fäden, Avalonia-12-Fallen, Prüfliste. Die Oberfläche hat **keine** Testabdeckung — Abschnitt 4 ist deshalb Pflichtlektüre vor jeder Abgabe | | [ToolDevelopmentGuide](ToolDevelopmentGuide.md) | Ein neues Agenten-Tool bauen | | [InstanceSetupGuide](InstanceSetupGuide.md) | Eine Instanz einrichten | | [Teststrategie](Teststrategie.md) | Was wie getestet wird, Fallkatalog | diff --git a/docs/WebUI-Leitfaden.md b/docs/WebUI-Leitfaden.md index 6001679..d2bb5ea 100644 --- a/docs/WebUI-Leitfaden.md +++ b/docs/WebUI-Leitfaden.md @@ -4,7 +4,7 @@ Für die zweite Oberfläche von ClawdDotNet: eine Weboberfläche im Browser, neb der Avalonia-Oberfläche und gleichzeitig mit ihr. Geschrieben für **Gemini 3.8 Flash**, das die Oberfläche baut. Stand: 2026-09-06. -Gegenstück zum [Oberflächen-Leitfaden](Oberflaechen-Leitfaden.md), der für +Gegenstück zum [Oberflächen-Leitfaden](archiv/Oberflaechen-Leitfaden.md) (seit #764 im Archiv), der für Avalonia gilt. Vorhaben im Deploymentcenter: diff --git a/docs/Oberflaechen-Leitfaden.md b/docs/archiv/Oberflaechen-Leitfaden.md similarity index 97% rename from docs/Oberflaechen-Leitfaden.md rename to docs/archiv/Oberflaechen-Leitfaden.md index d46d122..803a050 100644 --- a/docs/Oberflaechen-Leitfaden.md +++ b/docs/archiv/Oberflaechen-Leitfaden.md @@ -1,5 +1,9 @@ # Oberfläche — Leitfaden +> **Archiv seit 2026-10-02 (#764, Stufe 3).** Die Avalonia-Fenster, für die dieser Leitfaden +> galt, sind entfernt. Die einzige Oberfläche ist die WebUI ([WebUI-Leitfaden](../WebUI-Leitfaden.md)). +> Aufbewahrt wegen der Begründungen darin. + Für alle, die an `src/ClawdDotNet.Desktop` arbeiten. Stand: 2026-08-23. diff --git a/docs/umsetzungsplaene/WebUI-Only-und-Englisch.md b/docs/umsetzungsplaene/WebUI-Only-und-Englisch.md index 218826f..2d35668 100644 --- a/docs/umsetzungsplaene/WebUI-Only-und-Englisch.md +++ b/docs/umsetzungsplaene/WebUI-Only-und-Englisch.md @@ -134,6 +134,17 @@ Probelauf am selben Tag mit `CefGlue.Next.Avalonia` 152.7977.831 (CEF 152, net10 ### Stufe 3 — Avalonia-Fenster entfernen (Flash: mit Vorsicht) +**Stand 2026-10-02: erledigt, vor Stufe 2 gezogen.** Der Mensch hat so entschieden, weil CEF +Avalonia 11.3 braucht und der Instanzprozess gar kein Avalonia mehr laden soll. Vorher +nachgezogen, weil Stufe 0 sie übersehen hatte und es sie nur im Fenster gab: +Telegram-Client-Anmeldung (#794) und Update anbieten/einspielen (#795, im Manager; unter systemd +über `clawddotnet-update.service`). `ClawdDotNet` ohne Schalter startet jetzt den Manager (unter +systemd über den Dienst, nie doppelt) und öffnet die WebUI im Systembrowser, bis die Hülle aus +Stufe 2 das übernimmt. `instanceWindows` in `manager.json` wird gelesen, aber nicht mehr +ausgewertet; die Kette „Fenster nach vorn holen" ist entfernt. Das Linux-Paket hat 38,8 MB, +mit `systemd/`-Vorlagen, und ist auf der VM Ende-zu-Ende geprüft (Instanz anlegen, kopflos +starten, anhalten). + - `Views/`, `Controls/`, `Converters/`, ViewModels der Fenster, `App.axaml` — weg. - Avalonia-Pakete aus der `.csproj`, soweit die Hülle sie nicht braucht. - `Program.cs`: ohne `--headless`/`--managed`/MCP-Brücke startet künftig die Hülle. @@ -264,3 +275,5 @@ Stand 2026-10-02, erhoben gegen `main` (c03d6d0). Quelle je Zeile: die `[RelayCo | L9 | Agent „jetzt laufen lassen" | nein, Endpunkt da | nein | | L10 | Automatische Sicherung einstellen | ja | nein | | L11 | Sicherung hochladen / als neue Instanz zurückspielen — vom Menschen am 2026-10-02 für Stufe 1 bestätigt | ja | Upload → ja | +| L12 | Telegram-Client-Anmeldung (Code, 2FA) — in Stufe 0 übersehen, gefunden in Stufe 3 | ja → **#794** | ja (Zugangsdaten) | +| L13 | Update anbieten und einspielen — in Stufe 0 übersehen, gefunden in Stufe 3 | ja → **#795** | Update-Agent → ja | diff --git a/src/ClawdDotNet.App/AppHost.cs b/src/ClawdDotNet.App/AppHost.cs index 97e7365..43de8c7 100644 --- a/src/ClawdDotNet.App/AppHost.cs +++ b/src/ClawdDotNet.App/AppHost.cs @@ -306,14 +306,10 @@ public sealed class AppHost : IAsyncDisposable /// public bool IsManaged { get; init; } - /// - /// Telegram-Anmeldecode und 2FA-Passwort. Null lässt die MTProto-Anmeldung aus — - /// im kopflosen Betrieb der richtige Weg, weil ein Eingabefenster dort einen - /// Dienst dauerhaft blockieren würde. - /// - public Func>? TelegramLogin { get; init; } - - public Func>? Telegram2FA { get; init; } + // #794: Hier standen TelegramLogin und Telegram2FA — Rückrufe für einen Eingabedialog. + // Null liess die MTProto-Anmeldung aus, im kopflosen Betrieb der richtige Weg, weil + // ein Eingabefenster dort einen Dienst dauerhaft blockieren würde. Die Anmeldung läuft + // jetzt über die Weboberfläche (TelegramLoginBroker) und blockiert nichts. } /// @@ -496,7 +492,7 @@ public sealed class AppHost : IAsyncDisposable host._shutdown.Add(host.LicenseWatch.DisposeAsync); } - await host.ConnectTelegramAsync(callbacks, logger); + host.ConnectTelegram(logger); await host.StartDeploymentcenterAsync(loggerFactory, ct); // Die Oberflaeche bietet die taegliche Sicherung an und schreibt Uhrzeit und @@ -1068,35 +1064,20 @@ public sealed class AppHost : IAsyncDisposable return AdminResult.Success("Telegram login started."); } - private async Task ConnectTelegramAsync(Callbacks callbacks, ILogger logger) + /// + /// #794: The Telegram login runs through the web interface, in the background, so the HTTP + /// interface the code has to come in through is up first. Until #764 a desktop dialog asked + /// here and the start waited for it; that window is gone. + /// + private void ConnectTelegram(ILogger logger) { if (TelegramClient is null) return; - // #794: Without a dialog (every instance without a window), the login runs through - // the web interface - in the background, so the HTTP interface it needs comes up. - if (callbacks.TelegramLogin is null) - { - _telegramLogger = logger; - TelegramLogin = new TelegramLoginBroker(configured: true); - TelegramClient.OnLoginCodeRequired += prompt => TelegramLogin.AskForCodeAsync(prompt); - TelegramClient.On2FAPasswordRequired += () => TelegramLogin.AskForPasswordAsync(); - StartTelegramLogin(); - return; - } - - TelegramClient.OnLoginCodeRequired += prompt => callbacks.TelegramLogin(prompt); - - if (callbacks.Telegram2FA is not null) - TelegramClient.On2FAPasswordRequired += () => callbacks.Telegram2FA(); - - try - { - await TelegramClient.ConnectAsync(CancellationToken.None); - } - catch (Exception ex) - { - logger.LogError(ex, "Telegram: Login fehlgeschlagen"); - } + _telegramLogger = logger; + TelegramLogin = new TelegramLoginBroker(configured: true); + TelegramClient.OnLoginCodeRequired += prompt => TelegramLogin.AskForCodeAsync(prompt); + TelegramClient.On2FAPasswordRequired += () => TelegramLogin.AskForPasswordAsync(); + StartTelegramLogin(); } /// diff --git a/src/ClawdDotNet.Desktop/App.axaml b/src/ClawdDotNet.Desktop/App.axaml deleted file mode 100644 index 4b234d1..0000000 --- a/src/ClawdDotNet.Desktop/App.axaml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - diff --git a/src/ClawdDotNet.Desktop/App.axaml.cs b/src/ClawdDotNet.Desktop/App.axaml.cs deleted file mode 100644 index 4102e1d..0000000 --- a/src/ClawdDotNet.Desktop/App.axaml.cs +++ /dev/null @@ -1,995 +0,0 @@ -using System.Diagnostics; -using Avalonia; -using Avalonia.Controls; -using Avalonia.Controls.ApplicationLifetimes; -using Avalonia.Markup.Xaml; -using Avalonia.Threading; -using Avalonia.Layout; -using Avalonia.Media; -using ClawdDotNet.App; -using ClawdDotNet.App.Services; -using ClawdDotNet.App.Settings; -using ClawdDotNet.Desktop.Services; -using ClawdDotNet.Desktop.ViewModels; -using ClawdDotNet.Desktop.Views; -using ClawdDotNet.Web; -using ClawdDotNet.Core.Instances; -using ClawdDotNet.Core.Storage; -using Microsoft.Extensions.Logging; - -namespace ClawdDotNet.Desktop; - -public partial class App : Application -{ - /// - /// Schalter der Befehlszeile, mit dem sich ClawdDotNet auf eine bestimmte Instanz - /// starten laesst. Gesetzt wird er nur von der Anwendung selbst, wenn der - /// Instanzdialog einen Wechsel verlangt — deshalb ist er nirgends dokumentiert. - /// - private const string InstanceArgument = CommandLine.InstanceArgument; - - private AppHost? _host; - - /// Die Weboberflaeche, falls sie eingeschaltet ist. Sonst null. - private InstanceHttpHost? _web; - - /// Vorgewaehlte Instanz aus der Befehlszeile; wird genau einmal verbraucht. - private string? _preselectedInstancePath; - - /// - /// Vom Instanzmanager gestartet (--managed). - /// - /// Dann gehoert der Instanzwechsel dorthin: Der Manager haelt die Fenster aller - /// Instanzen im Hintergrund und holt das gewuenschte nach vorn (E-M2). Ein Fenster, - /// das sich selbst mit einer anderen Instanz neu startet, naehme genau die Instanz - /// mit, aus der heraus jemand wechselt. - /// - private bool _managed; - - // #576: Muessen leben, solange die Anwendung laeuft - eine eingesammelte - // Registrierung meldet sich ab. - private System.Runtime.InteropServices.PosixSignalRegistration? _sigterm; - private System.Runtime.InteropServices.PosixSignalRegistration? _sigint; - - /// - /// SIGTERM und SIGINT beenden auch mit Fenster geordnet (#576). - /// - /// Kopflos war das seit HeadlessRun verdrahtet, mit Fenster nicht: Unter Linux - /// reagierte die Instanz auf SIGTERM gar nicht und wurde nach Ablauf jeder Frist hart - /// abgeschossen - beim Abmelden, bei systemctl stop, beim Herunterfahren. Derselbe Weg - /// wie die Bitte des Instanzmanagers: das Fenster ohne Rueckfrage schliessen, das - /// geordnete Ende laeuft von dort. - /// - private void RegisterSignals(IClassicDesktopStyleApplicationLifetime desktop) - { - void Beenden(System.Runtime.InteropServices.PosixSignalContext context) - { - // Abfangen, nicht durchlassen: Sonst raeumte die Laufzeit den Prozess ab, - // waehrend das geordnete Ende noch laeuft. - context.Cancel = true; - var signal = context.Signal.ToString(); - - Dispatcher.UIThread.Post(() => - { - _host?.LoggerFactory.CreateLogger("ClawdDotNet.Shutdown") - .LogInformation("Signal {Signal} empfangen - die Instanz endet geordnet.", signal); - - if (_host is null) - desktop.Shutdown(); - else if (desktop.MainWindow is MainWindow fenster) - fenster.BeendenOhneRueckfrage(); - else - _ = BeendeGeordnetAsync(desktop, signal); - }); - } - - try - { - _sigterm = System.Runtime.InteropServices.PosixSignalRegistration.Create( - System.Runtime.InteropServices.PosixSignal.SIGTERM, Beenden); - _sigint = System.Runtime.InteropServices.PosixSignalRegistration.Create( - System.Runtime.InteropServices.PosixSignal.SIGINT, Beenden); - } - catch (PlatformNotSupportedException) - { - // Ohne Signale bleibt es beim Schliessen ueber Fenster und Manager. - } - } - - public override void Initialize() => AvaloniaXamlLoader.Load(this); - - public override void OnFrameworkInitializationCompleted() - { - if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) - { - // Erst beenden, wenn wir es sagen: Zwischen Instanzauswahl und Hauptfenster - // ist kurz gar kein Fenster offen. Mit OnLastWindowClose würde die Anwendung - // in genau dieser Lücke aussteigen. - desktop.ShutdownMode = ShutdownMode.OnExplicitShutdown; - - _preselectedInstancePath = CommandLine.ReadInstancePath(desktop.Args); - _managed = CommandLine.IsManaged(desktop.Args); - - ApplySavedThemeEarly(); - ApplySavedLanguageEarly(); - - desktop.ShutdownRequested += async (_, _) => - { - // Reihenfolge: erst die Weboberflaeche, dann der Aufbau. Andersherum - // bediente Kestrel noch Anfragen gegen eine bereits geschlossene - // Datenbank. - await ShutdownWebAsync(); - if (_host is not null) await _host.DisposeAsync(); - }; - - RegisterSignals(desktop); - - // Nicht abwarten: OnFrameworkInitializationCompleted muss zurückkehren, - // damit die Nachrichtenschleife anläuft — sonst gäbe es keinen Faden, auf - // dem die Fenster des Startvorgangs überhaupt erscheinen könnten. - _ = StartAsync(desktop); - } - - base.OnFrameworkInitializationCompleted(); - } - - /// - /// Setzt das gespeicherte Farbschema, bevor das erste Fenster erscheint. - /// - /// Das Ansichtsmodell des Hauptfensters tut dasselbe — aber erst, wenn der - /// Aufbau steht. Dazwischen liegt die Instanzauswahl, und die waere sonst bei einem - /// Benutzer im Dunkelmodus hell und der Rest der Anwendung dunkel. - /// - /// Ein zweites Laden der Einstellungen ist unbedenklich: Load liest nur und - /// schreibt allenfalls beim allerersten Start die Vorgaben fest. - /// - private static void ApplySavedThemeEarly() - { - try - { - var settings = new SettingsManager(); - settings.Load(); - ThemeManager.Apply(ThemeManager.IsDarkName(settings.AppSettings.Theme)); - } - catch (Exception) - { - // Ohne lesbare Einstellungen bleibt es beim hellen Schema. - } - } - - /// - /// Setzt die gespeicherte Sprache, bevor das erste Fenster erscheint. - /// - private static void ApplySavedLanguageEarly() - { - try - { - var settings = new SettingsManager(); - settings.Load(); - LocalizationManager.Instance.SetLanguage(settings.AppSettings.Language); - } - catch (Exception) - { - LocalizationManager.Instance.SetLanguage(LocalizationManager.DefaultLanguage); - } - } - - private async Task StartAsync(IClassicDesktopStyleApplicationLifetime desktop) - { - var result = await AppHost.StartAsync(new AppHost.Callbacks - { - SelectInstance = SelectInstanceAsync, - License = new AvaloniaLicensePrompt(), - IsManaged = _managed, - TelegramLogin = prompt => AskAsync("Telegram Verifizierung", prompt), - Telegram2FA = () => AskAsync("Telegram 2FA", "Bitte 2FA-Passwort eingeben:") - }); - - if (result.Error is { } error) - { - await new AvaloniaLicensePrompt().ShowErrorAsync("ClawdDotNet – Fehler", error); - desktop.Shutdown(1); - return; - } - - if (result.Host is null) - { - // Abbruch durch den Benutzer oder fehlende Lizenz — beides ist bereits - // erklärt worden, hier kommt keine weitere Meldung hinterher. - desktop.Shutdown(); - return; - } - - _host = result.Host; - LocalizationManager.Instance.SetLanguage(_host.Settings.AppSettings.Language); - - HookErrorReporting(_host); - HookLicenseWatch(_host, desktop); - - // Nach dem Aufbau und vor dem Fenster: Die HTTP-Flaeche braucht den fertigen - // AppHost, und ein belegter Port darf das Fenster nicht aufhalten — TryStart - // gibt in jedem Fehlerfall null zurueck und schreibt den Grund ins Protokoll. - // - // Sie ist mehr als die Weboberflaeche: Immer dabei ist der Socket im - // Instanzverzeichnis, ueber den der Instanzmanager die Instanz erreicht (#528). - _web = InstanceHttpHost.TryStart(_host, _host.LoggerFactory); - - var mainViewModel = new MainWindowViewModel(_host) - { - // Wer beaufsichtigt wird, wechselt nicht selbst. Der geprüfte Befund des - // Aufbaus, nicht der Schalter der Befehlszeile (#535): Wer --managed ohne - // gueltige Unterschrift setzt, ist eine eigenstaendige Instanz und darf - // wechseln wie jede andere. - CanSwitchInstance = !_host.IsManaged - }; - - // Der Wechsel gehoert hierher und nicht ins Fenster: Er braucht den Aufbau und - // die Lebensdauer der Anwendung, und beides kennt nur diese Klasse. - mainViewModel.RequestInstanceManagerDialog += () => _ = SwitchInstanceAsync(desktop); - - desktop.MainWindow = new MainWindow { DataContext = mainViewModel }; - - // Der Manager bittet ueber den Socket, dieses Fenster nach vorn zu holen (E-M2). - if (_web is not null) - { - _web.Control.FocusRequested += () => BringToFront(desktop); - - // Und er bittet, zu enden. Ohne diese Zeile lief die Bitte ins Leere: Der - // Endpunkt nahm sie an, antwortete mit 202 - und niemand hoerte zu. Der - // Manager wartete seine Frist ab und schoss den Prozess dann jedes Mal ab. - // Kopflos war das verdrahtet (HeadlessRun), mit Fenster nicht; und mit - // Fenster ist die Vorgabe (ManagerSettings.InstanceWindows). - _web.Control.ShutdownRequested += () => Dispatcher.UIThread.Post(() => - { - if (desktop.MainWindow is MainWindow fenster) - fenster.BeendenOhneRueckfrage(); - else - _ = BeendeGeordnetAsync(desktop, "Instanzmanager"); - }); - } - - desktop.MainWindow.Show(); - desktop.MainWindow.Closed += (_, _) => _ = BeendeGeordnetAsync(desktop, "Fenster"); - - await OfferUpdateAsync(_host, desktop); - } - - /// - /// Meldet ungefangene Ausnahmen an den Fehler-Stream des Deploymentcenters. - /// - /// Erst hier verdrahtet, nicht in Main: Vor dem Aufbau gibt es weder - /// Einstellungen noch Token, und ohne die wäre der Meldeweg ohnehin der Leerlauf. - /// Die Kehrseite ist bewusst in Kauf genommen — ein Absturz während des - /// Starts erreicht das Deploymentcenter nicht, steht aber im Protokoll. - /// - private static void HookErrorReporting(AppHost host) - { - AppDomain.CurrentDomain.UnhandledException += (_, args) => - { - if (args.ExceptionObject is Exception ex) - { - // Der Prozess endet gleich: kurze Frist, dann weiterlaufen lassen. - host.Errors.ReportAsync(ex, fatal: args.IsTerminating) - .Wait(TimeSpan.FromSeconds(3)); - } - }; - - TaskScheduler.UnobservedTaskException += (_, args) => - { - _ = host.Errors.ReportAsync(args.Exception, fatal: false); - - // Ohne Observe reißt eine unbeobachtete Ausnahme in manchen Konfigurationen - // den Prozess mit — und das wäre eine Nebenwirkung des Meldens. - args.SetObserved(); - }; - - Dispatcher.UIThread.UnhandledException += (_, args) => - { - _ = host.Errors.ReportAsync(args.Exception, fatal: false); - - // Ein Fehler in einem Ereignisbehandler soll die Oberfläche nicht beenden. - args.Handled = true; - }; - } - - /// Ein Widerruf beendet die Anwendung, ohne Beenden-Rückfrage. - private static void HookLicenseWatch(AppHost host, IClassicDesktopStyleApplicationLifetime desktop) - { - if (host.LicenseWatch is null) return; - - host.LicenseWatch.Revoked += async message => - { - await new AvaloniaLicensePrompt().ShowErrorAsync("ClawdDotNet – Lizenz", message); - await Dispatcher.UIThread.InvokeAsync(() => desktop.Shutdown(2)); - }; - } - - /// - /// Fragt, ob ein verfügbares Update jetzt eingespielt werden soll. - /// - /// Bewusst eine Frage und kein Selbstlauf: Wann aktualisiert wird, entscheidet - /// der Benutzer — eine Anwendung, die sich beim Start selbst beendet, um sich zu - /// erneuern, ist genau dann im Weg, wenn man sie braucht. - /// - private async Task OfferUpdateAsync(AppHost host, IClassicDesktopStyleApplicationLifetime desktop) - { - if (host.Deploymentcenter is null) return; - - // Die Prüfung läuft nebenher; kurz Zeit geben, dann aufgeben. - for (var waited = 0; host.Deploymentcenter.Update is null && waited < 10; waited++) - await Task.Delay(TimeSpan.FromSeconds(1)); - - if (host.Deploymentcenter.Update is not { IsAvailable: true } update) return; - - var notes = string.IsNullOrWhiteSpace(update.ReleaseNotes) ? "" : $"\n\n{update.ReleaseNotes}"; - - var install = await ConfirmAsync( - update.IsCritical ? "ClawdDotNet – Wichtiges Update" : "ClawdDotNet – Update", - $"Version {update.LatestVersion} ist verfügbar.{notes}\n\n" - + "Zum Einspielen wird ClawdDotNet beendet und danach neu gestartet.", - confirmText: "Jetzt installieren", - cancelText: "Später"); - - if (!install) return; - - await StartUpdateAsync(host, desktop, update.LatestVersion); - } - - /// - /// Die Reihenfolge ist der ganze Punkt dieser Methode. - /// - /// - /// Dem Watchdog sagen, dass gleich ein Update kommt — sonst sieht das - /// Verschwinden der Instanz aus wie ein Ausfall. - /// Geordnet herunterfahren: Datenbank, Scanner, Telegram, Abmeldung. - /// Erst dann den Agenten starten. Er bekommt unsere Prozesskennung und wartet, - /// bis wir weg sind, statt über gesperrte Dateien zu kopieren. - /// Selbst beenden. - /// - /// - /// Die Verlockung wäre, LaunchUpdateAgent das Beenden zu überlassen — - /// das tut es aber über Environment.Exit und übergeht damit Schritt 2 - /// vollständig. - /// - private async Task StartUpdateAsync( - AppHost host, IClassicDesktopStyleApplicationLifetime desktop, string version) - { - host.Deploymentcenter!.AnnounceUpdate(version); - - var settings = host.Settings.AppSettings; - - // Vor dem Aufbau: Kestrel darf keine Anfrage mehr gegen eine geschlossene - // Datenbank bedienen — und schon gar nicht, waehrend der update-agent - // gleich die Dateien darunter austauscht. - await ShutdownWebAsync(); - await host.DisposeAsync(); - - var problem = host.Deploymentcenter.StartUpdate(settings, AppHost.AppVersion); - - if (problem is not null) - { - await new AvaloniaLicensePrompt().ShowErrorAsync("ClawdDotNet – Update", problem); - - // Der Aufbau ist bereits abgebaut — weiterarbeiten wäre nicht ehrlich. - await Dispatcher.UIThread.InvokeAsync(() => desktop.Shutdown(1)); - return; - } - - await Dispatcher.UIThread.InvokeAsync(() => desktop.Shutdown()); - } - - /// Ja/Nein-Rückfrage. Avalonia bringt kein MessageBox mit. - private static async Task ConfirmAsync( - string title, string message, string confirmText, string cancelText) - => await Dispatcher.UIThread.InvokeAsync(async () => - { - var completion = new TaskCompletionSource(); - - var confirm = new Button { Content = confirmText, IsDefault = true }; - var cancel = new Button { Content = cancelText, IsCancel = true }; - - var window = new Window - { - Title = title, - Width = 480, - SizeToContent = SizeToContent.Height, - CanResize = false, - WindowStartupLocation = WindowStartupLocation.CenterScreen, - Content = new StackPanel - { - Margin = new Thickness(20), - Spacing = 16, - Children = - { - new TextBlock { Text = message, TextWrapping = Avalonia.Media.TextWrapping.Wrap }, - new StackPanel - { - Orientation = Avalonia.Layout.Orientation.Horizontal, - HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Right, - Spacing = 8, - Children = { cancel, confirm } - } - } - } - }; - - var answer = false; - confirm.Click += (_, _) => { answer = true; window.Close(); }; - cancel.Click += (_, _) => window.Close(); - - // Schließt der Benutzer das Fenster, gilt das als „Später". - window.Closed += (_, _) => completion.TrySetResult(answer); - - window.Show(); - return await completion.Task; - }); - - /// - /// Holt das Fenster dieser Instanz nach vorn — auf Bitte des Instanzmanagers. - /// - /// Die Instanz macht das selbst, statt dass jemand von aussen an ihrem - /// Fenster zieht. Der Manager kennt kein Fenstersystem und soll keines kennen; er - /// bittet über den Socket, und wer ein Fenster hat, holt es nach vorn. Kopflos läuft - /// die Bitte ins Leere, und das ist die richtige Antwort. - /// - /// Das letzte Wort hat der Fenstermanager. Windows lässt einen Prozess - /// im Hintergrund den Vordergrund nicht einfach an sich reissen — Activate - /// blinkt dann nur in der Leiste. Der kurze Ausflug über Topmost bringt es in - /// den meisten Fällen trotzdem nach vorn; unter Linux entscheidet der Fenstermanager, - /// und manche sind da streng. Mehr als bitten kann eine Anwendung nicht, und mehr - /// sollte sie auch nicht tun. - /// - private static void BringToFront(IClassicDesktopStyleApplicationLifetime desktop) - => Dispatcher.UIThread.Post(() => - { - if (desktop.MainWindow is not { } fenster) return; - - if (fenster.WindowState == WindowState.Minimized) - fenster.WindowState = WindowState.Normal; - - fenster.Show(); - - var vorher = fenster.Topmost; - fenster.Topmost = true; - fenster.Topmost = vorher; - - fenster.Activate(); - }); - - /// - /// Instanzwechsel aus der laufenden Anwendung. - /// - /// Ein Wechsel im laufenden Prozess ist nicht vorgesehen und waere auch keine - /// kleine Sache: Engine, Scanner, Telegram-Anbindung und Datenbank haengen alle an - /// einer Instanz. Statt das umzubauen startet sich die Anwendung mit - /// --instance neu — derselbe Weg, den auch das Update geht. - /// - /// Reihenfolge wie dort: erst geordnet herunterfahren, dann den neuen Prozess - /// starten. Andersherum liefen kurz zwei Prozesse auf derselben Datenbank. - /// - private enum StartModeChoice - { - LaunchManager, - Standalone, - Cancel - } - - private enum StandaloneSwitchChoice - { - LaunchManager, - SwitchStandalone, - Cancel - } - - /// - /// Instanzwechsel aus der laufenden Anwendung. - /// - private async Task SwitchInstanceAsync(IClassicDesktopStyleApplicationLifetime desktop) - { - if (_host is null) return; - - if (_host.IsManaged) - { - await new AvaloniaLicensePrompt().ShowInfoAsync( - "ClawdDotNet – Instanzwechsel", - "Diese Instanz wird vom Instanzmanager geführt. Gewechselt wird dort — " - + "er holt das Fenster der gewünschten Instanz nach vorn, statt eine " - + "laufende zu beenden."); - - return; - } - - // Im Standalone-Modus den Benutzer fragen: - var switchChoice = await AskStandaloneSwitchModeAsync(desktop.MainWindow); - if (switchChoice == StandaloneSwitchChoice.LaunchManager) - { - LaunchInstanceManagerAndOpenBrowser(); - return; - } - if (switchChoice == StandaloneSwitchChoice.Cancel) - { - return; - } - - var viewModel = new InstancePickerViewModel(_host.Directories, _host.InstancePath); - var window = new InstancePickerWindow { DataContext = viewModel }; - - // Schliesst der Benutzer das Fenster, gilt das als Abbruch. - window.Closed += (_, _) => viewModel.CancelCommand.Execute(null); - - // Umgekehrt: Sobald eine Wahl feststeht, schliesst sich das Fenster von selbst. - _ = viewModel.Result.ContinueWith( - _ => Dispatcher.UIThread.Post(window.Close), TaskScheduler.Default); - - if (desktop.MainWindow is { } owner) await window.ShowDialog(owner); - else window.Show(); - - var path = await viewModel.Result; - - if (path is null) return; - if (string.Equals(path, _host.InstancePath, StringComparison.OrdinalIgnoreCase)) return; - - var executable = Environment.ProcessPath; - - if (executable is null) - { - await new AvaloniaLicensePrompt().ShowErrorAsync( - "ClawdDotNet – Instanzwechsel", - "Der eigene Programmpfad ist nicht ermittelbar; ein Neustart ist von hier " - + "aus nicht möglich. Bitte ClawdDotNet von Hand neu starten."); - return; - } - - // Neue Instanz mit UseShellExecute = true starten (keine geerbten Datei- oder Socket-Handles) - try - { - Process.Start(new ProcessStartInfo(executable) - { - ArgumentList = { InstanceArgument, path }, - UseShellExecute = true - }); - } - catch (Exception ex) - { - await new AvaloniaLicensePrompt().ShowErrorAsync( - "ClawdDotNet – Instanzwechsel", - $"Neustart fehlgeschlagen: {ex.Message}"); - return; - } - - // Hauptfenster sofort verbergen, damit es nicht eingefroren sichtbar bleibt - if (desktop.MainWindow is { } mainWin) - { - mainWin.Hide(); - } - - await ShutdownWebAsync(); - - var hostToDispose = _host; - _host = null; - if (hostToDispose is not null) - { - await hostToDispose.DisposeAsync(); - } - - // Sauber beenden - await Dispatcher.UIThread.InvokeAsync(() => - { - desktop.Shutdown(0); - Environment.Exit(0); - }); - } - - private static void LaunchInstanceManagerAndOpenBrowser() - { - var exePath = FindInstanceManagerExecutable(); - if (exePath is null) - { - _ = new AvaloniaLicensePrompt().ShowErrorAsync( - "ClawdDotNet – Instanzmanager", - "Die Programmdatei des Instanzmanagers (ClawdDotNet.Instanzmanager.exe) wurde nicht gefunden."); - return; - } - - try - { - Process.Start(new ProcessStartInfo(exePath) - { - UseShellExecute = true - }); - - SystemShell.OpenUrl($"http://localhost:{ManagerPort()}/#/instanzen"); - } - catch (Exception ex) - { - _ = new AvaloniaLicensePrompt().ShowErrorAsync( - "ClawdDotNet – Instanzmanager", - $"Konnte Instanzmanager nicht starten: {ex.Message}"); - } - } - - /// - /// Sucht die Programmdatei des Instanzmanagers. - /// - /// Die Pfade werden aus Segmenten gebaut, nicht als Zeichenkette. Hier - /// stand @"..\..\..\..\ClawdDotNet.ManagerApp\bin\Debug\net10.0" — unter Linux, - /// dem einzigen Zielbetrieb, ist das kein Pfad, sondern ein einziger Dateiname mit - /// Rückstrichen darin, und die Suche ging dort nie auf. - /// - /// Die Entwicklungspfade bleiben, weil im Betrieb beide Programme - /// nebeneinanderliegen und der erste Versuch trifft; sie kosten dort nur zwei - /// vergebliche File.Exists. - /// - private static string? FindInstanceManagerExecutable() - { - var exeName = OperatingSystem.IsWindows() - ? "ClawdDotNet.Instanzmanager.exe" - : "ClawdDotNet.Instanzmanager"; - - var nebenan = Path.Combine(AppContext.BaseDirectory, exeName); - if (File.Exists(nebenan)) return nebenan; - - string[][] entwicklungspfade = - [ - ["..", "..", "..", "..", "ClawdDotNet.ManagerApp", "bin", "Debug", "net10.0"], - ["..", "..", "..", "..", "..", "src", "ClawdDotNet.ManagerApp", "bin", "Debug", "net10.0"] - ]; - - foreach (var segmente in entwicklungspfade) - { - var pfad = Path.GetFullPath(Path.Combine( - [AppContext.BaseDirectory, .. segmente, exeName])); - - if (File.Exists(pfad)) return pfad; - } - - return null; - } - - /// - /// Der Port, auf dem der Instanzmanager seine Oberfläche anbietet. - /// - /// Aus manager.json gelesen und nicht fest eingetragen: Wer den Port - /// dort ändert, bekäme sonst einen Browser auf eine Adresse, an der nichts - /// antwortet. Diese Anwendung kennt den Typ hinter der Datei nicht — sie liest das - /// eine Feld, das sie braucht, und nimmt bei jedem Zweifel die Vorgabe. - /// - private static int ManagerPort() - { - const int vorgabe = 7000; - - try - { - var datei = Path.Combine(AppPaths.ConfigDirectory, "manager.json"); - if (!File.Exists(datei)) return vorgabe; - - using var doc = System.Text.Json.JsonDocument.Parse(File.ReadAllText(datei)); - - return doc.RootElement.TryGetProperty("webUiPort", out var port) - && port.ValueKind == System.Text.Json.JsonValueKind.Number - && port.TryGetInt32(out var wert) - && wert is > 0 and < 65536 - ? wert - : vorgabe; - } - catch (Exception) - { - // Eine unlesbare Managerdatei ist kein Grund, den Browser gar nicht zu oeffnen. - return vorgabe; - } - } - - private static async Task AskStandaloneSwitchModeAsync(Window? owner) - => await Dispatcher.UIThread.InvokeAsync(async () => - { - var completion = new TaskCompletionSource(); - var l = LocalizationManager.Instance; - - var managerBtn = new Button - { - Content = l["desktop.startMode.managerBtn"], - Classes = { "primary" } - }; - - var switchBtn = new Button - { - Content = l["desktop.standaloneSwitch.switchAnyway"] - }; - - var cancelBtn = new Button - { - Content = l["common.cancel"], - IsCancel = true - }; - - var window = new Window - { - Title = l["desktop.standaloneSwitch.title"], - Width = 540, - SizeToContent = SizeToContent.Height, - CanResize = false, - WindowStartupLocation = WindowStartupLocation.CenterScreen, - Icon = owner?.Icon, - Content = new StackPanel - { - Margin = new Thickness(20), - Spacing = 16, - Children = - { - new TextBlock - { - Text = l["desktop.standaloneSwitch.warning"], - Classes = { "h1" } - }, - new TextBlock - { - Text = l["desktop.standaloneSwitch.text"], - TextWrapping = TextWrapping.Wrap - }, - new StackPanel - { - Orientation = Orientation.Horizontal, - Spacing = 10, - HorizontalAlignment = HorizontalAlignment.Right, - Children = { cancelBtn, switchBtn, managerBtn } - } - } - } - }; - - managerBtn.Click += (_, _) => - { - completion.TrySetResult(StandaloneSwitchChoice.LaunchManager); - window.Close(); - }; - - switchBtn.Click += (_, _) => - { - completion.TrySetResult(StandaloneSwitchChoice.SwitchStandalone); - window.Close(); - }; - - cancelBtn.Click += (_, _) => - { - completion.TrySetResult(StandaloneSwitchChoice.Cancel); - window.Close(); - }; - - window.Closed += (_, _) => completion.TrySetResult(StandaloneSwitchChoice.Cancel); - - if (owner is not null) - await window.ShowDialog(owner); - else - window.Show(); - - return await completion.Task; - }); - - private static async Task AskStartModeAsync() - => await Dispatcher.UIThread.InvokeAsync(async () => - { - var completion = new TaskCompletionSource(); - var l = LocalizationManager.Instance; - - var managerBtn = new Button - { - Content = l["desktop.startMode.managerBtn"], - Classes = { "primary" } - }; - - var standaloneBtn = new Button - { - Content = l["desktop.startMode.standaloneBtn"] - }; - - var cancelBtn = new Button - { - Content = l["common.cancel"], - IsCancel = true - }; - - var window = new Window - { - Title = l["desktop.startMode.title"], - Width = 540, - SizeToContent = SizeToContent.Height, - CanResize = false, - WindowStartupLocation = WindowStartupLocation.CenterScreen, - Content = new StackPanel - { - Margin = new Thickness(22), - Spacing = 16, - Children = - { - new TextBlock - { - Text = l["desktop.startMode.question"], - Classes = { "h1" } - }, - new TextBlock - { - Text = l["desktop.startMode.explanation"], - TextWrapping = TextWrapping.Wrap - }, - new StackPanel - { - Orientation = Orientation.Horizontal, - Spacing = 10, - HorizontalAlignment = HorizontalAlignment.Right, - Children = { cancelBtn, standaloneBtn, managerBtn } - } - } - } - }; - - managerBtn.Click += (_, _) => - { - completion.TrySetResult(StartModeChoice.LaunchManager); - window.Close(); - }; - - standaloneBtn.Click += (_, _) => - { - completion.TrySetResult(StartModeChoice.Standalone); - window.Close(); - }; - - cancelBtn.Click += (_, _) => - { - completion.TrySetResult(StartModeChoice.Cancel); - window.Close(); - }; - - window.Closed += (_, _) => completion.TrySetResult(StartModeChoice.Cancel); - - window.Show(); - return await completion.Task; - }); - - private int _beendetSich; - - /// - /// Das geordnete Ende dieser Instanz — der eine Weg, egal wer darum gebeten hat. - /// - /// Erst auslaufen lassen, dann abschneiden. Laufende Agenten und - /// beanspruchte Aufgaben bekommen ihre Frist - /// (), bevor Weboberfläche und Aufbau fallen. Ohne - /// das endete eine Aufgabe mitten in ProcessAsync und bliebe bis zum Ablauf - /// ihres Lease auf running stehen. - /// - /// Und nicht im Rückruf von desktop.ShutdownRequested. Avalonia - /// wartet dort nicht auf async-Behandlungen; was länger dauert als ein - /// Wimpernschlag, läuft gegen einen Prozess, der schon weg ist. Deshalb erst - /// aufräumen und dann Shutdown rufen — der Rückruf dort bleibt als - /// zweites Schloss stehen und tut dank der Sperren beim zweiten Mal nichts. - /// - private async Task BeendeGeordnetAsync( - IClassicDesktopStyleApplicationLifetime desktop, string grund) - { - if (Interlocked.Exchange(ref _beendetSich, 1) != 0) return; - - var host = _host; - - if (host is not null) - { - host.LoggerFactory.CreateLogger("ClawdDotNet.Shutdown") - .LogInformation("Beendigung angefordert ({Grund}).", grund); - - try { await host.Shutdown.BeginAsync(); } - catch (Exception) { /* Beim Beenden zaehlt, dass alle Schritte drankommen */ } - } - - await ShutdownWebAsync(); - - if (host is not null) await host.DisposeAsync(); - - await Dispatcher.UIThread.InvokeAsync(() => desktop.Shutdown()); - } - - /// - /// Faehrt die Weboberflaeche herunter, falls sie laeuft, und merkt sich, dass sie - /// weg ist. Mehrfach aufrufbar: Update, Instanzwechsel und das gewoehnliche - /// Beenden nehmen denselben Weg, und der letzte von ihnen soll nicht ins Leere - /// greifen. - /// - private async Task ShutdownWebAsync() - { - if (_web is null) return; - - var web = _web; - _web = null; - await web.DisposeAsync(); - } - - /// - /// Instanzauswahl beim Start. - /// - private async Task SelectInstanceAsync(InstanceDirectoryManager directories) - { - var preselected = _preselectedInstancePath; - _preselectedInstancePath = null; - - if (preselected is not null && Directory.Exists(preselected)) - return preselected; - - // Hier steht bewusst der Schalter und nicht der geprüfte Befund: Diese Methode - // läuft mitten im Aufbau, bevor es einen AppHost gibt, der geprüft haben könnte. - // Sie entscheidet auch nur, ob ein Dialog erscheint — wer --managed ohne gültige - // Unterschrift setzt, bekommt ihn nicht und wird gleich darauf trotzdem nach - // seiner Lizenz gefragt (#535). - if (!_managed) - { - var choice = await AskStartModeAsync(); - if (choice == StartModeChoice.LaunchManager) - { - LaunchInstanceManagerAndOpenBrowser(); - return null; - } - if (choice == StartModeChoice.Cancel) - { - return null; - } - } - - return await ShowInstancePickerAsync(directories); - } - - private static async Task ShowInstancePickerAsync(InstanceDirectoryManager directories) - => await Dispatcher.UIThread.InvokeAsync(async () => - { - var viewModel = new InstancePickerViewModel(directories); - var window = new InstancePickerWindow { DataContext = viewModel }; - - // Schließt der Benutzer das Fenster, gilt das als Abbruch — sonst wartete - // der Start für immer auf eine Auswahl, die nie kommt. - window.Closed += (_, _) => viewModel.CancelCommand.Execute(null); - - window.Show(); - - var path = await viewModel.Result; - window.Close(); - - return path; - }); - - /// - /// Einzeilige Abfrage — ersetzt Microsoft.VisualBasic.Interaction.InputBox, - /// das die Telegram-Anmeldung an Windows band. - /// - private static async Task AskAsync(string title, string prompt) - => await Dispatcher.UIThread.InvokeAsync(async () => - { - var completion = new TaskCompletionSource(); - - var input = new TextBox(); - var ok = new Button { Content = LocalizationManager.Instance["common.ok"], IsDefault = true }; - - var window = new Window - { - Title = title, - Width = 420, - SizeToContent = SizeToContent.Height, - CanResize = false, - WindowStartupLocation = WindowStartupLocation.CenterScreen, - Content = new StackPanel - { - Margin = new Thickness(20), - Spacing = 12, - Children = - { - new TextBlock { Text = prompt, TextWrapping = Avalonia.Media.TextWrapping.Wrap }, - input, - ok - } - } - }; - - ok.Click += (_, _) => window.Close(); - window.Closed += (_, _) => completion.TrySetResult(input.Text?.Trim() ?? ""); - - window.Show(); - input.Focus(); - - return await completion.Task; - }); -} diff --git a/src/ClawdDotNet.Desktop/Assets/Fonts/Barlow-Bold.ttf b/src/ClawdDotNet.Desktop/Assets/Fonts/Barlow-Bold.ttf deleted file mode 100644 index 2f20cbe667ca5cd871410dc50dc4b1a30c1d6267..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 108220 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 diff --git a/src/ClawdDotNet.Desktop/Assets/Fonts/Barlow-Regular.ttf b/src/ClawdDotNet.Desktop/Assets/Fonts/Barlow-Regular.ttf deleted file mode 100644 index bb3faec4e243e812b288fbfb9235b12ea781eee4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 104068 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 XP1fFtvE1>5t`jFbIJjcyDERvy)saR} diff --git a/src/ClawdDotNet.Desktop/Assets/Fonts/Barlow-SemiBold.ttf b/src/ClawdDotNet.Desktop/Assets/Fonts/Barlow-SemiBold.ttf deleted file mode 100644 index 7c974a4aa67c689a4b2a844b48f624cb4eeaa6bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 108348 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�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 DmH8Q(>sFWG+yuqSVE@{Rl|dhdKwsR# z^NdX^p5u<`kP7>tdO4)7vo_(2Xaj!nRL`o}@+&wTRMpU-Rk9no*x9Sl9)1>&ZPG}j z<7W1hK?jH8jx3x@(dHg<>fn%lYT;~==N~RdQBqLUR8PaBw$D=|&nJg8G$`C&`Dv89QC;AjY~oE( z3MU-Aqv@S4N={Us4$Lkaq}l3GZBoOPR;zj4Wv~`r@p|oVmw|SAC{6y%Btrg`PV-D>Rr#ph)wA&+di~{Vrfc*FE}VaGY)aP zy*XA~Qd~@)(pm~lEz*ie5-le!aV*+}4^J++qWuL1BA?YSV99#4xzJd1G$I%ZaIn_f zZk5eNncI+);k}y-_x%@|_5}jjy7$1sy%)caXxb4v@#cfMN&6;Q!XNadA;zdr^FY@u zk=fKp0)ry>2-9IzB z-?8)@Kbv`Vt<9^kJ?RHN^v2oJ&zxi75U;FyE|RPJ@XCkz#M&PM4$mhrjrytoV(B_Y z8)!bU>ffgN&N)^aXzW@zTjl9J>jAAP;%W_Oohzz><;n1vQwW;E{*SO@1u^4T<`4`M zlw#F0qi%+^v4gFL6l zjm(bGy65OWIE#wWZ*B|I{w6%0=KJcN?d=C=2TmUJkZ%WvXm8cCNyhiVsSb_gIK1$F z_Eq?wf4>o4*g6k|z9DBl>Y@D`+Uv^a$yQTW$)9jLshs@t?B@sHt^)tV_|~2y)?{2h zpUZO)*Gl#!+f^vPT4EOk^#{-fT65&%m%@<}g3v_?@~QEg=@T3k?95Gbt2 z!p>UhTb67gyLe~~$>uFB^xeEi6SWG!w24(f-U*ocH02*N0r{GFoN3G( zlU%QlD6S6VC}Z9vGI-N5iIk3-cKmVrpwhbhfuO ztUK%}^u7W)$1pKye}TqSt#BE-;aUqb*GLf=O2G-u<6)$K}(O|r)r%T*`s?t6oW2r1*pZjQtDve7ew>-$F{FUS!gp5*rPK&)*lv{&cWxI6=@#gmkpUtOgcF?|Op zEGd27m);8N?^?bJ-=+#ta^ck=&JvfDja#dM+n%o;6x?x^xK1T+ADG`kl zE?18`f9JSP1b$!ocAs+}ue{gR$)iu?kDE&Nz>9yGK*x9bU`%y*I$26h?1Pkg>7h zA8sre@+M6R!i_iS_(?OTcC?Odo*0~nW)CkZ2o(713jB%i5Ty6iljJUGfS!bBoSY`$ z5j)|K(i)sLKhilayb!x1*!E41sMxeLS2PdvPnMhLiY@0bjFD|Ri&oVVL*w(CR zgYsszo^R?+zVf^QUg=fdk>g7S8d?tCMXT2ZDk}qZe=iLL^`d}3fU#PSdF|)WMLF=x zo^5Y%48V3r90-pXNbLF9zYs%4+@T$iY>Win(9__rBzDlAA5U()>F4Wn87>|R2ciL# z*+IPHprk0@ho=szYr^pYj@afXU69NQR>3JQ zKtx$#Lsf|{x41ahSE7s=6Zf_rpPY=zDADqi?}fqTKNns9BlZ7}P!;g2eIwUHK8wYY zNqgeaDZFgRITWGkc$tM_XBs+(S$rXUZFDAr_T93*H6AD^)N zwJa-nK|Lb)>%cPOXI+2b5JSwrF0N1 zKQm#}G&~Gr(drY;D^JrHgl&gdm_Fr7?P$Sera>#yV3cSM4$B6E;g0>@V-n2i@G*&s z;$at;h<()-iL?F^P;+sW*>f;$Y#^ zn+Ag?n{-a1g5t4rbvXVYIHk$ToEEgn)`t!nVy~7)(TCXYU%qUTu{8@Y%Z zT@g$eh+*N+SB4$~R|VO8)>z;eD1`6Oq%f9`{m4%8R$xzRV9Kkcah$a|n|+;#6Z(L!mPqWEKdAf0|0E&TMIKZ^^92 zuqZ3i^`dNFNr}&jr!f;T7?P8ZZ{0g_1`muEk6u%db10{P#VFj@P3Y@z=<7MbxWP5~ z89E|}ZHG)P1_(}N(x|7X5cFasZRm&H%>#p(5GS0H((sxfOErWq%?`%2jtw@KmlYNp zv?G_1o-s&Sd;DNNtI!4rLxRe$QWRxXgddi&1!hM2NM+5KZkN+z?C~_<*z^c(Zb!%5 z;?}a7EG(jx)~35Om-IkxQUXfXTiq_xm94bnbnGvB&R|NlMEt!}!)+@$N!8aq7v^+*D6tSDKg<%LbwqA(}fk7m_SsI#}=O$ zZ1_frPua0CS&|4nB1xHp@%9PY>K!=(ZD^|Zk1Hsu_s7yXCVPUi9NYbhRlPsT*=?;a z>*{*R+HGbodAxhdnvSy(r?VqG_pXT8tsy7)(Z88}B(IHq;?1VnjLUsx@NDR0+9RZ> zZnz{U;tjq&9M=-qX0>;PpoYj4fG8q76QifxSJqTe;4gqPKf5e|emD~`4yD;Mv8`&- z(s+6aPss9Y^Bqj5+0YuEi7=SlGbXe{|8~rIrkLj0yw~)`KxO_wkM7b(O_(`;Z|kgC ztrz^YGSHyw4S~wAZatf2VK2+VX4@_z-ElUr8&J;chGjk14Xj@#1IGZb#)$O~K)vC( zlXYOG!s$DooQaAa$0X?Ft4KTyNK6Y)_wOX`2OtY z+|BDPtNgyG^0RrpWtHC_UC!$*tNbFl(5dI_sPawpe6F9`Me8sNpWD?>|1QS+8^Y~5 zo7Z6${x*d-SUUJSoq8^lO}0L2|=wGDV(fKYBh zr*y68lCkY%Z5sW@G^}yhV^1q0zitd|>0i!jG9DI=_)%&^w-woK?A=V&Xm zU5biO9UQht5&g9!XjUSiw1&)HsGUMg@i|ycV;@XG=juA2KEyOHCC}xp6wikhL--98 zFormKp)VRXVd`4*0!2j>)CYr)VqVZg%K}xPHcj6;1J)cT|iPJ7MyOX)af_!r`Ai zhB?MGTiwQX9vj?W*2C}GdibPXzC9^m?Lm3|0o+7nN{$pR!~tU;Dts=ng-^{0EIow) zJ$SdJt^tQr{6UIENJ01xdt;-bQ=;cmaybbO8qNBR`cJ;W4`}?U8=UnHm6LA{!XB&9vSP`c}gZzRNQ46N>!Gt5-;uH%)3Ldo8HM zh?Lmt;&Qm5TyFfoEiTw~;lMr1QPm$ys-w{j1Kgo|m^U+!V;J}(1oOhmBGhs~2 zh+%{4(aP#ZaH;@@q`)cL$RmC7eazw=PYOB=zZm(j1D_K(HE}?nagaCCB2B zlzqq>NcnY*0p4ijcr_YgR>(QVRybh88j0jEkj$H}^$F((er3I}J4Tn7(5$EDn9onceh%M{`c*fBAP;_0wX$6}Fa z&ktirGmgZo0(fT_eqHAZg1DltARaX~7Vk^Uh)qjQKviadP7@?Yy;DdzoAQ2tdmxZK z$REh2AQrPtwFk1Z1O7qTfur}C@+0hZWtiYtG1|2Wb6WUp-N+v}TUX4LITf%z@S_fE zzX>PD$af+hr}EHY{Q48`Gg#%9;+!)LWn!Ub8B#J?l)F@V3+u@Gw~=t{~ElJE8M?N*{^He zx0UZ#p*KP`;#S-jgPp`VmJDRW+hW-WkO58ODN=`L5Q}gGItL?{Aqc%M&km-tGz^N( z&PYwN-D5&^Eym3=)p--ovh^oUama=~YZu1q859`bt`!1mBJ8A2nl~2+oiNrcT?Q^?G74~>kQTP!r_No^=B3iu7JPI-G zw%~1Vq(f-D(OI=ZQ5r0=&hKGmhfAzDM)o?xH>B?wK4<_60KgK=KEnq;vK^jVPg+2p zYq&dbhHsgs&XnHCUTumrhSQldKErnbwosnH`@pWomj6T8f&aJ5I9_SnP3AkdjdTH6 zX3d!=_tXVwe>IxA73~j?C+BPz%KJO3T5XM|9%ofaojy+c%vc-Hb2j6hc)jK;AA!}`RSxhI<~zK z0PMlO2-yNU{Lk2h!1zHR6n@iH7p^Lo3(GS5B0JJiRbx>dV$=flw3hERIrf-?oFCSF zgPF!M;OJZBjD}en$nh0MzL3*YYJFB)9_HrM<~*g(p3;3crq7AxH8o{4dq(A;j`21n zm7YEt#%w;`MsLsWI;QTn2Qa-O+Slr83fQ4_au5-zYP+8qmU8Gb_s7Qni zfeI64cn)NF#8{y@0B`RjT^Y7h@+FnSe@^Z`>R)IYYy}FvsnN)gOvW8;`P=|bq zFdJN@trF-$yc$Y}USzA>)|Cio#zrM^egLY%za_meOuYJ(PBtjiilIJWt*>?D~wwl&Ty9w_^@mUg<;kk&FRMPy~ghgcl0 za4aW>bYwSMG{`|XI)nJ_@x*)e}&f++NX)225A@9q}{ub@P=C_VuGdU zE4?PH2O?nr+tZ1qF03sZc{av&0I`{^fpNhRLz`-<%8E%sN(xG1u$PpK^)nqwBI%}h z_+EQ*mCDb7(EZwG&d8{{C&goUGu&EiVMhD_ydXH<9h2;FyEENdd|6s-TB4R1=RU7r zBXeU+yy;FcJUKbBc)_p>zg)?NCpQ~5eXOy*j|JL;j^sC_IFnxIF~_oD^#kWI!`>3u z|2U5swII82?!5MndGk7arKQ+9Eb)1cACFy;S*o={_Mwd9Hp2CjFOJq-v@Ww^Cg?tneX#Ef z$39Rw$3EEQ;n)Xm7y07s@^I_}my>;Cmxp5?tmhj}IX}OjeurZpta=dpVAsR354=vK zebWxOa>~W52hyXoTdxz5yl2+WiAabw9h!tH?14ciB8&XdCn6p95bNsjiAcD$d+&)% z)H4Rm!=A{zcIQYW#Q;=STTJ(r$^%;3@Bo<3?6;0Yy4@`~^DO>D62JS?PS^Y~W0|JG%lnQ`$nZnxolZi6L%miZBmInm(P`ZHoqYOofl7ePU93`K~Y3=Xa@N90sS98N-M&bdZbpWzLv5yNV# zd^x3ju8~bH+Mp#{z&_Y$pKRo@h3$SQm5dC9gY@>v#$NTZVqjb#A@Ogz@!U(HXUa>63gpLkRIv&^{Rs;t2U4{-F zI&SFL;D`b^GU0$I@WtX-VSf%@CM5`Jdvhsdf+HpZg<*dYk*<+kM^L`3w$zzXK2FFm zoSc)(G_7n33HRi3O)KwcpVz&!#M;v)F>p z#;x7|sg;4Dx;_-!H#Bbz35}AQKnohjOM_-6yq^f^gmWZbw>ISq-CFpb3eoFarYP@G0F#c4p^2WG?i`WRCqTpRCbTK0hG#*;s8 z6#G8yJ@{PgZ~3h~conq=Pg~I%tSGW35D?voj)gg3?ZLCQ)yOYuZPE8Y`A_e`!{15o zN_r7Ol$;zDoYFljdjHe1my2N9=ZXmrWYKmWEGT*fSu#m#C-fK#p&eO(|GJq(65}0? zX%52S3wSdg%9vvre3lBKNU(-5*4%h~bJ!sjv2tX5vRfs{n79O2Y%WEe&?-j`3Mv(& zd)vI4p|s}m?l)oS!%!ZIqZSiUJ@hcydqu3D%cu>o6X4*<Ah#)dIn|%h5=NTh=K?sGO`E?xFF&VD5z0fKn?l}i5Psw zJd+q-OceE*XGG%`qd}CZe*f>Bd#kIudtgl7)1j;CuIGH`JKw%I$2;=JAuA){iKN@m z%J11_m|LHAk&3qo!83`d)~j)np}Q|_Gt3C28Cpq}}i?35+aGwSh z=)aIL>84CxzhBHC=%zW+5DLdK@x8P2d&O1}ZEgwI1tW?6#PXtNZpWG1k@^yaCM8vpB;txU%8`_yaC0OB+0;vCR2E&moE0jm5~{;$QYC1$jMY(0%_(Rq zO~hoKRQ{WD=buVwvdhMY@&P=m%xQI!>!Z^z4dETL2;xb0OCPW-b&5D}@A3acwT-#JfBI3tqTLkq= zBiLx{-;TfX2fXY@sd(s23@ za85Ng1KcgyaU&)~%n)+|J}dS)BlqKY3ps3hrrBocpt?$ktMH{@Y?In#Hk-oOP?3Z3 z8@#sn3~INUDg_gc5lyLa7%55|P_j2Ju@B3iI0#RiJ3HF1HCTXclBNNZfH!Y<@TzO& z1$4YStF>xVk0T}wXr(mXO2vvWKXyDH2?qO)^uSR77*RV~D2o63T&Op?u7*<|>SbUX zuBNBauB%`Hhd%S>iII7Hp9)6EmsX2lIGuOSEwD>qZ2IKB?i5>~am(?^aZ@}1(VtOC zf7Ef(<<#-F(0uaO!=FaS3;b!6ui?hJuYIQLPgBQ9-%`)K)rqa6dOHLo_qZEtzV^I8}J|Xn&PPU2&TsoM=mWbWJRe1=jY}b14dnmU)pgX zqOzbh7M;RD!asH#+l8_vvJ|SB(h|K`h(T#Wann52CfR5u2>VpF=QBLks!V~aYa&uI zFnxIH6vE%h7;xBT--2T;fF zMvj#G-ZKTb@n-fw{`l+2Um)QR{R*Kcz#Yd2{W$CrJv+2|%jm1HuR zY-Wq}Pj^Sc%F%|quvVn0Wioz}ZKyQOOSwSvHZjT3Sf!zln${>R>hp%(Rfe6lf$!7x zUh~H-^9m?Mukd{SeBIbshhDc%9bqN*;(h3iLhC@s$%d$Gi*$Sk9bfqcj*~1HWJU{Z=RTT+w-=KkB%oKT2khd_mTO@G_VkWPwX^bVvaP$c};#F*luA zCC56srxeslNyKmCuVdc50vW^{ZCt#20qE~`Z{s8g?lFiOa$`VEG!sTFtOm}TX0~M ziCK&gIoG+5z(Td0|5PLOvRPy`f8Hx`mBuS+GzGj6|Grhi8uCcd@jKb43yu>HR@dLk zq%WD|m!j)$XR{I>&@0iem*9aM<#2u3YL0S#8Dhh+Aty%}7B7%g;(Uck$`FT%7=ZlZ zESbVWA-};vQ`l1g2kjQ{k=ocmm`127vySnBn3G9e zh%89q4iXMIo0y(MHsjZE z%(XBU6UT{)zu~1~TVVg9dnta7Y)I4D$(8{4E#+`PMWOI$%{YzfUDOcdGz1;0=!J4I z_+>7;#w3&PY%NIA@SIPQMxp;@HA$nquX)@xip8ZFOohWigb#u8H3pF8Grw2b#6r0P zuF2A|RrZ1}-HCY&!fJaedr3UZEwcl4)R0^Nm%rpc&0ZPHW%M0gcES09y9xjjBWW5;T*bGtNlyI zKaM!hAo>g9I1DW6_!#WrI|)a%ae4hBy2H_ZuxRnWk+ClOQ9tc_S>Jp=D0UL&Q<8b9 z(qB(00`;_GB?Qc=rE<`w{10>xpb~XuJ{!95mZgeK9@O|%mH)`5*GYGJQ9{b=op5f% zJExY;dD}Vem^kMha1JLA9MH4_Ck`Atd}!~k?Tb`eee+w|d+zh8n?6h|GO2RI*)hHU-_P!*IVwbG5gn-mMyrA=r%w13WuO-%40Gkva7 z*jXa?ghXu(E{Y?tu+erXWj>#y6C&*cnJm=ThqOXv@y-<720tZf^g=kA;W=;3uHJ=R zah`W!mjov#;jq~;xqW^%JGObKucxy;9;M9fs&ctI%GT@-88)kE-MO_)Rkjv-C^Cid z9ach_yuC^ef9XUv{)Vgv>(tF>5PCCnq2P8~_$N-(^lI?qYvEJ`{o6Q%8c_yk|NY=H zBU@r7{i>o^YOGmerJG$N*Q^#16Mfo^3gA(pdx?V_g9cAjNNO%fyf&dddOSAhlx@%0 z!2Y5O3CyJ8tiNzM8xDu->L|7^+!yZcOebP>p}Mx_0OCIVl?twBK}PxH^Y2R6!e*Ff%hKh{Ui9eU9H>>()=Dwtf9zxS=~z3aw6_7w%UyYX4{ ze5^m#6dhQ{LB-CeXJK4guVv4|#JZk^_J6Zy;Z5SN43$u6{1vwN_l0pk=Ly~30X+qB zht1|hZae3HLOly#!+vhO+ki>lc#o_wxYy7RP|v~+OJs9TO5EYO7a+&Ly@bew@t5ma z7?;jd*;g%5+_TVL-?I?5gqot7tCiCAAtTt)XXTBDmmUz}u02PlIa~Ub(H~2vWBo_d z=_p+9L%Vki-Y#}5?r&q9rH-Ob)q9L&ES}1p>_{fNjgP_62RiivyOz&tG4dCdLSPDM z2(aS}g+Smt$fxHgX)%<)F!fUD`Nh{Mn{UkRZiwlvR7Z5t0{&t_B!o_*I_TX z@pTAEJc7GH;UO@n9)}?FYkM5p8}~S*5IYi!GvdC*Lx&dc+h=TUjj>o89ArT7eKWZi zX7=r7smSlcDI*8FyYv1B@P6uXi2kV90S5IsqzaULZJ$F>8dQy<;bA{IeGbvS8TZOQ zhu}S`ax=!T&ZT$GK8JlQi=n<#7*#@48RDJO(IEC@Mu?0-qvzvl*n$QY5ynr&gBUyr z48A{ZU@m~OgrQD$)|(|R-^GqYBb7X4+QntMhUUrH8!>(+?>Wh{kU2K!ap;g#xWzzG zogRnwdG=y6E%8KFwxm>=|SeiBh^g*^+MX_1UX^U60YwEw#e3ybG`Ii!Yl z4GT|g0Edkl7D~uCYg!1GJK525z$K7}%dO~UE@8(XTLZh*Yi?sz=XlQQ8r-h^=f>CY z-{jwQ5Bd}rtrOwY%A#C@Efm!hLkt@Q`m2?I<))|spR*Lyv=2)$I=nX;^oJ%x=ra5= zi$P{{GG>s~Q}y0cRuJ0wq}j@Pz{TrvrOwm&Y-Fk*ijJ?GU$nu3@N~3BB_hMnQBtB> z?>V^Y?3qjWxVB+mJvpO<+gA@POv8wj2JUF?Qh(2n@e=VBXPN?YH!gr1fkztCP zSNrf`n-}q38Au_uq&)8>NK3mj=H&^kjmr{*5^C zk|DZFr{CVKjJ#zoQ1^%}6d^jt4tb5IUEW7f8<41ad2!Q(>op_CU&U#*> zXx?kEej#m5AHKLu=K!B^`tT90QwpV;t6E9=u9BV{y9%qNr9=MD4W!(wFMM2_{iYB< zF$`xJpEHc-G`{kmnBC)e_xbnW%MWU!9(=S*9JF#%W(o(XhOG=jG!fSjg6uxU7qqVz%U&c%#jZZ}jh?cv3^CaB(QSx@Gk*dCV_C|g4 zVj=br-mpb9W0t7cTJ59kz&JalO zl|yK0s`F!fXy51Aa2S;;z(OV_hC-`@x)x1d4SNLk?P3R(;M=lfTkw z)%TR4zz7aaz4@AT1 z)1xoArbizPSF9UmNP)uA@4~z3>!PjSkFPvSgwtlrXb|{Oyge=K+#>*!!($09cS{-j zQG6p?)m*XcMz|oaAsJg;a~J9+7s=QTzR*16H4S&G^<&9ufy2pnO{Fo=w@A zGGBd-&hA}>#NE`6kHEq@bKe~u4P#SQG{F17*ir#pzR2}1P!z-n=l+nNcUgYkceCq@ zVS_zOGT3#neYiSmUgBEq$(LH+lMhU8Rg$6rD9o*(C*Lio9YeLP(EB6U7K^o6%iEZ? zeR+BN3JNmrPDYs>O(vtc-$j#oIq5nm$3gZ(*4h* zh^rj~&ZSoSp8?G0*Z)jM|1&pBi29#V;4twyc8A%>Soxu);ke1lO>fF;HgS&Mg9-Kf zcRIfwnF5iv*xfoJTv$~k809^7M%N>0TC4`NH4~l&kKL#1p)@UGJzAa#PayY%&VQoo zb;;;-%jP60SpsQp%)v0i?)6)fe95z8}Hm>fHjwP4_ z;oDi)`|Ksvy+5k=*%BEZUMs|FUBd%P-3-PiWB4~1L<9uP5V;RKn{ACf!Ut1ROMEc{ zQoR(X27Dz@zjAwvHzAk&{q=kT{mjnM`%H3hu$gte&xqlyZ#7nIqKzEbH?>155)W6W zQlSxWaXxWmaqf`uBarkCk$bT-k?1lWg@_IOAX(!EJ`O)bge)Fz@3T{dz0cg?)I$iY zkJJZSns9jyQqyf^ssc@tDk}aKC^p5T3Ln_Jb-SzHEL5dZK^hqQABPtg4jE7fNK?Jc z$ery-Bsz_csIethK8E`Gvv}D{^*u|HK)BlXjP|ii^>Yd<5I>;sMN0Hr)A!7OaHLQ6 zJ?q`PJUf8a17CzG+|f`Rx~eD3VA-a=(oxl2ma?*&EMb z4XIWbxK%w#UzB}7=`8uaXRy4(7E1yHNKGQrhN~N??-{_>3MpX?)M#NXPYXxTRgndr zh4pPrA5=>^y_}92Y#9!wcN?QYfN|9RxejX{t?ZHc%uC{##n&mDeg;_^y(x4}Q#O6qY#<3Q(lls+RU(HnjyO5e`L1a~{ z_-th*sU%ru;^)W+T6d{T2TFxE$CDNe{_A_J^}kd`&`ZOXT`@K6G+85)zgyE6Hvgf? zmjd~LoxXx5YffQbnErj+hF*Rl2&cm*2%L!VT>VVc9rHVLb4iY+7D@y1sElHLcv5p-F`(u96Zt$DzBzMag>3!Hc=WG7tV~t zHJB5i48wMJ2O8LVTUF)f2z)~d@Cx=cx0Pu*Zg+0?u{Io4Jw8^XK+CjF(5D-C7IqG& z@0!Gbym13-SY*9$3lgodUfdzwgL&8Bk)7-=$o^NvJ38X*?f7=h&LeoUe3#UbzUI(} zv0^=7gKO?&r_ON=+1u4~DDP&iO@8gWC}*U|mhQakOu=|4A7sPlNSnNR*FC5WQS=<( zM<;CZ1jCHhkxjLhaONhKJKemn%&`G0b{lu-#cJ$287o|Cj*49;Gs>E9WUA|=8erYR zyn6)OfnBnMW?b;^-@?61Ufxcz>!+}R?(-t{_?uq!K0bi=Z4kE(za_=3gJ=Ldk;Ek9 z)}h&-XD==}l(+NOdUpsmfsu@H8--r7_%^C~ab3m4lpDA1#kY2fTfZ5jyD|SMN9l!A zmFLbN&>k=ZeE5KrBmTj`?YpHMk+(~2aLt|U$#YyoF(&Fcx3bTxYYO5!*1qd@wzK#- zfFI&JP*Y_bUR1=n7xm)GFPZGcMQ}UsURcs_p4M_-EphdMUZDaJ|-Eb0<4o4CnlFXuZ^PZbe-WX^$*eueHy)9rp2JnC_oI@$_Xs84ZjU3*1JS;H@!oi*vjfkLMtf1Fqr?|TRju#)>b5X} z7!f7gq!g3=gld4Lbb-21BvIotMxDRB9=5M`q_!BN>E2P%0VZ6Nh;1Gp7Oh6Kp{1_+ zmEu`}f4tYIYizCB?#?8*5%G2hUCob>Bt}Q*Y}Y8f>Y( zskTM_d5;_|Z5}kI!FoK8*zpSNUR3+5$KsF(B(b%D5S1N4TqO&TYFATD=JkHVqG%F{ zsK8A0NTiM1*6)Y>)*sW6M5Fuo-{{^xul_%|$i??SHH^Zf@^pn!7vmb)+QjrDZt>Mq-0J}bA7u5{pVQXX+Rdt3MWUV#*2&$3kdO&gvT$#+&#X^=9 zkVC?F;NEs(b|{qJ**a3bgt%5M&1hNuaxs? zT3KN~#qT8f1yDc^RM7-&)I3L^-!#f}_hT?d^CrG6Q`6fUinLl51u9WU4!k@vg5Be0 zB(4o!m%{Q-;d`t>N`87EVcaSO<{prTF9`NABlm1;1p`@NRwTi88%FK~&b-$^Sgjbt zx~EtE6F!T-T5F?4FgT3P48vj!$;E`11sF+{PG8DK`v7D?u8Tc(Sn zq$M>U%FmtpY{X*dv+)|w4ssytY#IGA4C|=VCWOxc(Q27@(5s^y7~xbK{!srs*^vQJ z+4Ksm0k$M)5lY(uxoFO~>WF%)0UJwmpteR>TG~i^kf;dER=Z4^*C6!|I8_o5P=U2V z?Vo-s2t-B=%X&NKFhAuU6GqFC-jPIGTbzk)LO;5&a6u?szoUDf>}oh+n;p0By=1Dr zuQwGJBDMYKMZ3B$9*)0ehQ{2Ae4keXE~6Uy+Mq0>If$AMLAWVV0t#V~pdqJ0M1eU} zPDIu(2go>=mR__c$}GnseGw{NPDLVRnv0Y8R^wNKDaH?BluD{dFAk<8!$BMstXi6S z{k81X-m+~|)5|v1?%}#8(m1%ubt7h3UxF_P`v;T%xXwLWx@oRe`13I4+D^4CkeY%Xy3olM z!8;HvNk*p2U>n8sK&YJs!m_q&?Y%YqNb!{gz8#I$SqvihdEx}-DMOfDI|{t_4}-pA zKE{6vez)%3<wA9I9()#xX}O=XeHtCWcI{OCLv$ zysQl2gLNGB^O11IshgeYF-+s zJRqWQTge^et|%~-a&zGI#I8bV!42c{|p?2O?#Fh8|lc-Y~k8L7NBwk6D_^wd84 zpj9?7P-YrsgG~|7N<5I9-!VUnPGZyBj~v+!x>=dXWD>75^`<@3mxo$9$ER9Tv9|d* zxpf`fq#nYJ+V-sQ!+ekGCg4XZb*dH@=o;dR0I?(3eZWztaqbTp_pm7iwS6jc*z3?`&^rLSJy$k!wL03c!yfIk%CK zgKP4vgWc8k zOYAm(ZP50WRi@i3@9*60-;z#dspt_V5+5|v8k~!840um!>yQn1K@I19*5DG+e6h& z6b=Kp6cFZtBJYtUbR0H7H1s$YO?H7p+!!S#!Z!3$*8zuPi8zorNH`pUhrsQGK|7V) zWqrL;9#v6y5`+CU4h}m|qm=fmicxoRzm0BC2j;i#6P}|Advy~LO760}2d8E)usz_6rWI>xirTi%8xE9} zVmLj1D=$mU#PMG|*y$*L!Trp;o;9 z3)n^aNCtC;t%H3MbN-`w{ltHf*MHLC^)Cp1ujKW2Kw!E1ym|d*tkHWh-p$18d%)`} zO8zUnJ`)Yc*6@0A(~(fwODxQ#rXU9-yPSjDzt>|QoS!}5)4dR0O2E^jEit4? z6SD`Xe?-i_zjb(CkQ5e}UYwt;GYwnl4Kq{WaJqS{sWH#)pT!#b6}tzW7?$&V8uqs_ z+C|8JBp=`TuyCY+gMY^)4i>SHjX5}wO;SKf|A3aOY-51E1M$z+p@r#XpNAdWF?Sf4 zm~0BCbzafmGBPI)T2{2NIbwNCPpmmx!osY%qcJ(ZeQp+EbztX5x77$y5%23w+yhaj zE-*WFRji}6H5hJd>`XU?quYRgOBKK#e<^NH-xz<-CIuVv_k{Cv`gRQNYl?HL-}Q(ab75eGl7 z^jFvH?9J?exLO(hOsO|iTNn0PW?4-~XU*G7>~LLQxzDzdy%;5aUKQ;g%cOcohWg_J zqv=Eqs>Ma(!^81JM=FsT9!x~5J{ycQf}cYUsf^WkbmuM!hGPwZp_W*4s5uyJ0glE2 zmpi2%H%3|!I@y4syDZvb8}jI5ikG*yw~w`trjqe+Uyu|A#iiXXm}k>bM^%D&No4|D zR$Z_=m59UcJifhaDGmHgHHX@Pp93wM5kuuMtV4@42YlA6H+jsmvDO$4Sg}Sh?9}$& zV%(gY)LEcA(mKCmZmu=@-s!ePOMD?7Yl;%WVy<=Q@cvuGm5~hzHW|!9T9D2|Ge4)T zXz%D~chBfpcTIhLO?7>JwVlm;J+oyC{$z)m>;JyKS^mKuK}{9yb?hPV>&9$7#sYyC zN)0v+iTO~ps?OD>0dlOB{) zkp`+fBZn|Xq_t13DoMJ;%B5;3&r}(+p`gF2!Vfbb8}8~F3fA;;i%c_rBE(lk%r-9? z7>YMEHo`0*YP*Mq2m8k&+jQXplS3Iano|S3vcF;UbZAx{& z+GXh~9RUtUzN$9`*Q)pHFQVpT%l=58YEDK|sVUO%73X)67MeW#+6DT(G-NpX{jWUC z(-&_aGPp=XiS<`D36Ej78K}2m_&w$Vcm$^ZXTr#Gy&-7cU)NI0^l-8-S?xnIds%Hm zsIDPUh1?L`^n2`+fJF#Z5NvZ9Ed)B-02A02wH4sf8h($yq57FZ1s}S-gI&0xNVgBG zg>#qB)$L{cGiI?yx7SugnE~{JzRq{)-Yy>;8#;%=g+pbJikL8t3USmBnBw!c@83Xu zXV7Vl6nm=G^Mdvxtlyya+N>bG9tmW!umUx4N7!**yXQ#2RkrJsc_qJ4Z%7tgD=h)% zz8Jk_W1$Sh17!;6&#Pd{6o92%Cmgtj3}7?5B!HiiO8g_k7)Yo4O^%5&tF^^447<6k z8tJx3PWUq+Zlqd+{$MC+J`iZGK>vewq?nYL@o;%V{iaY^saO110FRApu;Nuo*xj+i z>H&{mu#aeQWQbjqw*e3^K%tZk0Gk!)4Rf}m;}=>0LV5Aw+*d(&iYH>O{=Yi=XkTnY z{ok3br_W_pKz(Hd82E*0_9qj)wu#-_J_s<>Y^tn9>yKbCZDtMA8wgO92D>TXeP461 zDh4&OvgI$khK9O;$+o|-(Z7Jj_NQXU^yUhGpcQuK*0TBYy3dm{(&!;ASfPRUpSO0foZDAFapA|e7&J?pU;BG zcnN&jZK%m^)RdR|`7T(T^_q$bv?B0VRMhC-(JR~P{r-kfG8w9BYOZWSk=csYnwt8G zU^voNS6NZtQn|O(N~NsQQtX7|KIQRoZX)(@4`j3mgp~YDD9oX94Nrqw|%lPD6iLoJS2)e8+kAc~)0&KA`-4=2d_LvC z=Timue@gqMeh}vgKI_jnu#aiK()T#<`LuKYr}OvwaL)=oU&3eo{pIYV+K=?zI8X3d zf4&~)f1w|6;3LmteOJe4j?KA+&T=K1JP zb{&ph4!x>WtIC!G1zZPCBuow*)HP-O5EuQ}J)zJW!AT!6t!~&katH8F{S`iSw!%J~KmY#q=i#&bfILs}6hD^dNiM_v3@$8URO~r* zKXT6Q+u(i^Yeesd9LHr(G+una$^Jv0hn&D=pFNJ!Fmil9lFv8UU(540&c9PWpWaL3 zf7&_!QF%UsUk_`i0qfhekDdLD!iBS+QMdp)9bEaScAxehtwgH>Yk|zIE#nT7k5K3= z)Jp*MJ9$hHfKV0C!FXmcw=o8q~{9^>1>V}4u3+yE~8GVL_h zJt*N8)c!@nO~$){mQRAueHn12-i^ouBmbnVEFe8!`Z3at&``?h%&02#cr#?&?st-4 zbZ7vQNdXfn5BCBuG&muKm@KjrZhTI#r(oC1iXW+tjg4WvpWf@kd!Lr?-KuI0`Q?Jp z2;lYrV2-#fzY5m_MkiL!Bin(>Gow?aDpV#xCSR{26r_K;O6n$6?{@|g6GIr+qVV#k zsr(Q9_pc&14n6A6@q9QJ5G(!_M2h!N);Mu?4Xy^nvs0_|8)?kPFer=+uEAr7ZZ}8G zZ87MOv7T6WJF28~nRoQbvf4YW6)c8Gt^$rHQN*?4_JG|(=-;ZBF( z+JL&+S7T54FppO*Jk|rI3|oPT*_aTS;Gv}=AcXh`nxKN2@YPbmb=i>-PJ-eKagC#rl)6my62tv*t)f+X9m~dSykwiy^sG?8>byT z+!aC>FvRM@Y_dvL@{b+YwzM_t@OD=M2+GY)g33TY%zL!2k=!T20|gS&))t;mO032i zrDl3+YJth`()mHew^VWSFz1JDvkG=gsD@F&R!=aNKfy#4E=ZJsU<2IKW^fN5M4ZT= z=?x0cAQbQ`gt!8t+93A?4RlN?IEkHiInikJhtaBej6aB~cqgI)8%`X(@ZjD( zOA9ko*|Fil$xtnN7>4|<WH}VbSm~zkb8&*FLz~alW4-!!|mf5r0{Q>+v6Z2p!nT z4g5YT82fLok>`TFa=y#p_iunnx-$k3_}wlc&cqc@jo#JZL>lY&pY z8J8tTGh@^^$4~nhrcAPBD!fuw6r$=N?lSzz4QvS=go5ntzXCyob@hSz2Gh(0>R}_u z-u&usB~z$dJ|qy7`M1{s6T-nKItGz56j**T7y*9JeBCj2XsA9{3b_F!27y}`(du1#oC4ByHNkxfyhY-kpf&nvINRWG^C9DoZ$h=f3K-vA%Tvi zdktfc!24*H2HL3MRpP~)@vJ6hvk*H}z%LZ8OTtd`a2wtdU3W*`Bz`T#ubGX9$-#mr zxzFKT`E8rDU$cX3>&rh^B9{za2(>i{mVgZPkH2;wO#JNEJoCpthjY}n$hptiV0;ue z^lDf;d|LEVo{Od&UU`nWf6AjxkwI7mS%liEglud3X@SBF16V9P-<7*L56R!!%Ewu= zl+&}CcJ^tK)A{GmKJCcqKpOTOYjNb!aJCIam-FQ(N0=*zst(~w4y^HLt!?YKuqIn~})i$i7AI zly3_byiI+-SD%pY?Bw40``q{AJOAREcVf#zZ@LHXEYVP#1W1LAjIm&f_*IEbQghEW;qI(BH-_uA3kdyG3PeH~9t`mU)!(qoy?tMfE6SN8jU}vCJc!A2F>N96H9>v1_=;`hafh9{^`~zplR@ z!b{O_iANI{=lvLGkWXWlI{w}-VbQ5wuKiq&A97wL!G^4KF0CYJ?TiPBQ*Au%pB0aA zqv7B+cnZB=bKgVYDH8v10oxf*$oCM)0Uk*u02qn_427mKd%%GgyzcU~v&DP3R?U8> zo#mg$eypYSaP|WhSR%_txCtvS(Ia&A4fPa!Z}OrEfe^iK#HSaZ?1!*_=Ksk#RkMH9 z{)GP--sR#X*sg<7hi@zdniFt2coc6Tm)y)mZ9EAxJw3u7Sx4YtM0&yMA8qH`c)hl ztT?|WB*xUR8=&(g(e@DS4@v!-8iw0wOmJg(ax(vQihUM!BASx2o_VqfDy!Hui0Znk zl@;^t8vDk`?vnh^?fv8sgq>E~j1pZz=-S&!r|s{G1LRvmO{in5SC@GpO6ZH|6*KQ+ z+8mKVu3Ze3n;ipSw&>d+e{b!}R8>ITOog32O}I;YU4Brt5~ai_&#pvrA_Ant$PYh$ zDK!QJ!H~x5s8ovCx7s*prO}D}d}E8QcWxQ!Ksc&pby^;zZG~GoD7Mi>XVI`TGqMFm z4#sUymu(@Tx;gjwTqZNi*j!I$?%%t0JP6k%bOU#`HgSEkCMc}QppkIgMJL%+H19W4RJ%=NvK3VgF|vb0IErG8>b=B zpd!wVq)4OQ8L$EHBKr-|ZLaMc-?DkIGaVl4_drIZ6xlTkPg~N#j^3!#C2uV*NKA3e z1}gQK-8wf0Ijc`FBfEfn*p6_xvp&(08ICVxal9AD$7bkwB$Q5X85wOmb+nWr0YFR` z%y)Pi)u3xS2KrJ>X-LZbi<#L&xBe^C<8cjAs*n* zVVBvf?auB=_BftXKMtoO7Zhz1O)p2Ts(7ewb>!xyrRBMB%}1gm=3 zTD}OI(SU{w{uDFea7Sh;Oh!ngfP}7CIxI#|+lg?%#uD=P0~q~n6ro&68wDhQ2sI*h z3YA)&;6nsMRtxVRs44)|!0%>fs_MYIQOqu6RqK;NY&SzFyVGzikItIUVWhU>C|m@4`IBFqyAI7U`o{@sNsALVN<0`I9oc29=Ev z@QN;dN03GYYAJ1By(nBy>)J|MyQwL$TP`k$ncIGJ?PjWKo=O z6D@jB`gB$5>k%fEhFBcVHRWRIj|D| zP*e9T7?yfeG2+@3`yst5&QapNvjK{m=ucauavZh6XwqQ?y} zER5@pUa>GsXy=VZMuxC#ICeBL4D&to_>~o2igntpZO#tPjtsSjq4Je@5f;K0pNO1cSA3>td+Nf4W5#@x(u=&6hY}ojbv88`toN!?V3;Z;2VV0t{#+l}2i>Rz) z$*Dm$0qpnZ{a3>iOC`*O-h2u zQ|pnn?b*}%>tR^DMu?k1U+FK_-?&MLn+*DUB}|dXirwMW_rVak7b&PvJkaWjB7KZu zIo*4OxL1CWKjB+iHY_{$Gu&7$?O09P7huEvXo2pmd^l1k&)aZ48`*GYy1$@IxvmWt z&IZ)>C!1IWc@mhCLE%}03<}FyfoCm%DyL!Ho&t5vJ*(SW;aPhGiLz%8IAeM}dw~5x z3u&=zm@?=fnIpRn<_IQ9&K9ZBg|yaQg1KrV>C%by&{eQUHq8S9sWbh;xKp@a*s7A?w&%{4Gr%ih|Ea(3KtacNKj#|<6QuhgI zs5?s*=O&GVuoG@0zZJa7yx1ePQrxkX%9z8Oq0t z6T#+2^qx@Ky$E|r?Jn>Dct99kW>Dy{c{&)Zs|$td{#-B#$@k)SZ8%iN9>#Gx7rY%( z8~%L?$3qC?43e!y`x4gb>sl0o<13&cEo+Zx738CM1vDgb8?HR!*g?p?a{=a_)W(^m z;@lFNZCUn}U}s#v%8Mjm;F+ae3WGfM$9{Y;egu(qjBiIBEh@&@>E3{xva0|TOG5`d z3&62FbeBenZYSwJs*uGDx{d1T|55Lu=)$=B9@zC?dR*BUF162K3NLfzGX9q>+cF#u z?GEk1pH|^fG6qmGZ(CJO<;eD*&$2^U*P0*LP-Ku$H(^)3o^$ln;GYrVf1!$`ZpX2! zBRH^Kh^uu*ryddFuXP4QPT*7+2M!AMM*UAfr}~Ay4;z1n`btOoguWX`P}WcM(O%Ss zvA(~9rtbO7CJlRNKqjpWMEYY9GQalMn&cO=Ow^CGm>-(!Pa!_D%PlMSj$zZ7we_2H z{U*bLkzD_TVQ;mKPXMdwxkGsF^YXb!mFj_hp&mF88ITFuNcfhIW)C2N{~eaaE{DWs z<$mgc=fWDxKMc)r=PZNXq1&?(AN|0wA^5UEM_14bfFIUSiBx*BnL^3O#wA8_jDfBl z#27%!vQ4#6ACc8g(o})X6@6UlI9h|9YkWv&mS$-pLmP~>#s*D-a(kJ$Y5kaQ1YBMz z$(6MKsPVw>$`5E=@c79YsNK}%?k1W8*&v&=JK3MHpJSdE1DCtHTT6cq-bo)-VZr^(nH>hDp_=tUglIo!D!shdX+Ch{YoTv#Gu$88E#G zTQAQhYNJ(+2-*#ldhE1q@UDqx%i$=oW5QE!dSl&XB^Bk>Rkj&G0^%MF52I*iU8svq zxkxcNzQ#=elC+0uXDA#DB|J5ptnSSa1ZY^5h23!Ae4^xbSjC$4*X!P_SHFpQ$Gixv zG1xxcJIcCz>^hiwZiO_!{K#tmskHYHf4Gld3Oi~OxYm$1pPlJ#trt{#6Xi%b^e~yI zCoHdS!i&8uzo4r-#%5|e)9L1BxOIlogFRi%spe!fjK?%aBT=7++9!}J8#)*qJ!I;T zJ}oKrlU+lD661krmrI)(8my&(3ft*Nh>!h#kx_&(OhZIa8orxZVVD==F znN){vq&gJL>sKbD$w~G+mc*EfOCz>A4DM4Vh@h#H{?p%g7^C)!W~% zvfxSa)XTV4FUmpzJ-7&EvOE+3LbokU{EZlgn#dXYa+&2vogr9LS1@Uje=sZ$*7N!zDZIvB{SkO2^Z8&32iaR7)vs~ib+s1zAT*p z2+?MJn|?jBr=gS00i0jt-X99_Ui0tZocOBEUWLQ8%>FfGl|C;G=f#`IRe=|{wH)Fk z&r#`6K^-?MNqb!kxIZwiMWr6^(^F(C@O7r5^l9+0Xva=!w zpJDZu@c`?^zXf##)piGGLwCE~jK$<|r{+69Xc)gE5;*us)1TZj@h zq86fLE(0k-m}`HcFOdRGv8aV8ExaT?B!@~P5y(v}N_!P!Cw*O#B92D$t7M2h9@WKV zS8TqpZ}`IA>0#)|C9(MCn(i7zcOY2Lni=ic-Mn|q!^$V4y<5k7`R4cTYH7OmLp>*^ z=T2slU}u*P_Lr4%PZsI*;dK1$v!@OjEYiMXa%`SPIkxgV{~Byvn}9(HP}{BAy$g>u zVEs~P@&=&C6I1criPacP_RWEKY+xW3AIOE{Q}O)2zQLF}EM*$xC+XjXJuAp9 zfP!Kyb^2sy*>~`%v$Ooi_~csS$~V}XP|p}O$j~@DEV0>bny6Kf%AwuhkA}SF#edtIH8Q$&Vk7>jrWok-4!5?IH?n zDLyW6TprT%m*UW}v-R6yHquOPo2Nh=G_S$Er_h2E(ioC?QN98uQ_nIid)6`PT))$K zLC^Y|G(%{{G6I$8PJv*ywRdKRAWnI??meBq8MBfve7Sp}r_>)hq-lq)JoKuQ7Xt#z z9r0K^mWaekVLXy@gxt#{N01;vperr4>Os~YyJG% znVa|42aaBzK;?ky{;rC)us+?lxde^?jyeOzmpvt+$YQq6zxC3=#oPDQ)h@hZu&xS4 ztHKmwR^Kvv>%q$S$p;VR8e1Al46kvGQB&XAP!sh|1+ceu_+Xyr0{Bn0rgv$VWXtDg zMth^dDvKK2QS}l;1o8&s65Y(L1;(O9aMduo*o>W z-Zi~*aO>byd#u_bUkwGVf+ei35Q%pk9JCipBV&46IK)2szw%v>SwxeOO*kxRN~QGh zVufiLQH9dj1!D=ya_{Wgb!4nx=b<*=ftlG0whZdLYZwj`yRL-W#-MF9#~9n5dnQuZ zimRjHrdXfOU&HlKv@?xx6vG4OR$I&dT~kL=%;*_PG|Vp_oF83IGh=GIVR%a7XsOOy zP4D1*bGDAcXa;6LPDZ%q97vX@=X~zlb4IYbtGqkbRD}pF{U|2z;@yyp zP@Ce#e}c$_&S2to2eX%KmUJr$ne}R{?<{20`?I1ERU)#mS<MU z9&$G$>FkZmkSG|!pd+oRU@}v-si8Jxn$h-yb2I46x+KC)P2rAAduL^!+MhyIwA8`b zWMxUEzpc8-^7$$fe{*2A94`DwM`y4p*-%lPXbYt?$=D{Y*Dv%;A3QV%pMy7o$hUZR zZEaIS483JLD!5)Z-Gk>}7Hwz_1)BU7{?_JtiqO)@*N2VtG}vbg?8zS|-EHA9%Gn-* z3kBhWS38y+@Eik`))4uQQmY>L{Lr0Rx4f76Ahj`l86P^VllaPZ2C|#gz4mF`jJi2k zzVp9(IU8(kEk~+D>rCtP#FouNy*(YNSfsqAycvl{#O0|sEGdx28vZ?o{i-OZq?|f~Gt8E(oLSvJtQ?{AIy7pXB#SQ(I%jD)*kB1j=FuPAuH;( zaitf?4^hj0ae!uJZHKwrj(t{taU+y$ws_$D2D=Vk9&&NdRH7v{E3A%PrdQ~+h4 z1LajcSZ(-9N$w)k z@tNdA1JatAUFC(wpqCf|P#dgk-eXkzN=tp!{HvMe{=o}+doLL5U(Vz{l$c2;w#MUI zp<*ZAQ>yD@T(|5kXp;v2ifE~;LmRg;QKI4>HX*O?7od5y@DOgzPK=~O$W$YLHWVKZ zKMnDW^IKrzAOf>Yp9qWhN&`Ne3Bv=u-N`svv~YiQFZ$X*g)R*CTh$Xop>VN^L2^0( z;(|lEg}}pMo!mr`G859tF~;8KMTrm8oaBg3F!dCyhzP@sdi8E_>mL4Qfk2NYn1y}- zLfUF{i`?Tv{6^=yEo%?ge~W_)!aB`eI_(k!!PR~1Udx6Y+fbLq7F8y^^m(|_z=QVZ?v^QqK)d;3Ca zd?=9^9!?~NNY7*J+12gK`{8wbMFqP&0vtc5Z_2fR0Emhix-1bcel{j{ zN!Q+PA$H3zyWq%&{qpS7pm!tEZ3SDv4=IKnIRuC&xeh!g4V@8^M|-5Mgh8;xF2p8; zZ3x#CMA4)Yt<5n~Tf$Q4rF}${TvjKf)dWXH4s%{GBl^-apv%&2p#KoSYS|3j9c>;@ zVrO>7Y=jHB0?i2<8aWG2cJyYC?%@;RrdxF0J=jni2(jZv!ee*tU7RuX8tzG1_^9Ff zmwFD5E{!amnd18O7dNpG$VB_Wj$n!#+a?R)x>@VWw&z_QQ@6V|5V(yV=P7ZWa8rB+M@S?W_k3e$X*d ziF+|Smq~F%OTZ!uj)7<}tOpneG(P6?dYDe(IEOnE#Dn6^b)>5?GAwp?#v^!2TO<^# zu|4P+MK)7dw6P`-g^bHW31;{V^pk>^W_wUZ&u97!^EB1B;wadCs*HKT zO1&0wTjBGFQ=6C%iBmrFRH(^ej6Mj~0Mf&LA@M|N8Ei$$EEh}prBHI|9TZ8hl-k7Z z!TzXGTU}nuxt$WmP`a$qXsZv@R05PzfKkHC*((a=81}b=U0;V335~A)U|)w()6i6f zN{k}bnfqD5pEernYvAaB4cLu2=6r&vJCNcz?QYPTQa5fKoYswrmDa^$xQOlS?WUMm z;x$!7F>93+9gFEy;yg|DMYr(BE$>s@YyX9OuEwv^{tnMQ?|Afb0EuWZ0aScRh%fQ$ z&@vML@VJ$g-1j)5V));{#&Vkn%gAqAxrpAgay?&K`8|#ozh|TP0*6;}5{ZYei2-jD)kniPh%*(ct~McMHs9 zn|1HzTTFczAL`ez`)Yc<`cGrIU-9u3$|tVV;_~fH6>ISYOoD=_qsYorzASeD(i#F9 zNfMT1^tt~4sWq*=mN|tw^_Cd}9gbn@eB3fGwX91ifP9McDGTfW?|AQXc(2Yskoz`) z0P7XQJC}~t;I@`k7_=>6}VS>9aus3R(xnu-+`_;+XO0%NWF0B%7S~X|le&vD_#x zw@a$Mh6ot?rVc+p01HBi>DxqM${wq^xx~jyJibj{Po?fLJdO3VW}W;5K=DsmklA@Yu}_?Gb-V zb!8dl-(qh2us44q_vSjfvAWmQCU?YI0B$tD*Sq)^3-&s)_FUS*`5hA9Z(`qA`A-DA zmAgA1VPk9U$K~3lIOU+Ypu>b^Fe=6FT5s_BTXc!h#z>ldLo`4e4Ydl()4Lg2(<`rE z>0Eh!<Gt;LGLJF$({?}<%5QtKS0nrg;qs4qkoFB%3v4!q`2oN1MbA{QTDemvgb zcd3pCbPl!~l4nS6k<6vGi%dOW)UnfurT3wPD6E`G-ARs9f6{R<^GE0YeCAyJ(z`2T0y>hKU?>5S}Z^+6}1~AF^yJCk-D}^dK&;KePNq zur?ZUNwfv?lVfC7hGi)#s3zs6Rb3wHPQz@7QJRUGa*qzHs`&}DXN`0WCJfy&Q(=EK zvsy7amir0MfFE9oHFWm_F^2*_p{gP-_k+uBp)2HmBF-YiOz zpvTOieh?H$bXc@INPW-|4)o$#icf%yR13QPG0AK0&^}AA!6U193N>BsM}C#VYbsxk z*VJg$nN?m>sd!C+h>dXG(4J9ZHB1MuX#t!N#6Hr&Q^aZNnwybuN{j~a>U^A)OP<>% zX&fqtV3RCjU8S3zUmJ-BU9?99Vkwc3(ZY37NS<3?$YFs)QJ;EvQSY)Vh3+LY}O zft#vnTT&ya^73RSSzL_dz$Ux3(Nt?S&dTIk-N|CKR9L?%zQp<<6YBg{*0*{LJ;mwR zZ8GDGuB*?l^X<+$bFBSV*l<+8iY5u|N+nJ}uwvI1%2ky`l2ox=rRe$yWVkuQ?m~?h zPnL6;Ilud2%}Nw5ACBsS79kR*DQi1=$Hy^?D+ivH@YSeLhIKgqAv0TzKwqw~9& zBt_s8+d+R{1m}yBB?kRgRY`9m!l$4Ptc#wBYe)_V$4mr6cvQUx$qGm@Q=H#TaKa{$ z*&N^scLYrX!BaK0Rkf_5ysXkjJvF^fhhftw;hwUJ5?_5|Ci)~~*D9}FQ&~|~?eln0 z&SA)g@xa&MK}#1;sv$;!KJbnJ{-1_bFHJcnEf_DweIlwrDe4=JIjyDO%Sh0ek&aK> z7b7DERybA~x43j~}=iEKo`&B2L_k(rgn$NAf=JwpK!fQ0{Jm+e7 zDf+YvpXdovkTqB)Rfz*%1Z$xnIGA=#-MknU7(T+`7z*MW)O4<&UcCg?g=H+ViQ*@? z7Gc0;t*xznt-YDhSRyWCv!$2M)w}a@Y+kbSY)E}`wT9PU;;k;*RE>47wmp@RmPk9G zW8-*4Y5|foOEo|kPy)UxYW$_;r6m=mzz&FrjkO7s6|35`2@>F~c?Cg|ZNTVZ!02=O zcmW*m&ONEULBWwC7;()v`1s0R-G^)L%za>jjCe_aV==!#Ov(B-It zSCAP`_4X&xj&-y$#K zIie%qwqCqXe%jVY&OW@-sejk##%~KdQ2h`0>Cdfz!Ro)k`Ttwn_rOJUT>H-q%fj+c z6hsuF7Z-@avhMOvL`2v>fJhV(6@=*iVSz>1Rag{=|6{Bn)}(2gTASL&CaI4!$wiGd zX_`l^O>AFkQe)FJNqu?w<=H-)m!^3(wRu*4-eucPefS@Y_|03WJ`1}lc zo(+Mw5%xCZflJ;IuzopJ&xyP9L^*C*98>QgDO5U z`d@4cP9^^t{u|*O^8NyW<>Rs&@WYv66a5KUL{AGa;X9b6V=zS0aVBK~uy~S9e}Jdx zLHI4+;QpfEXJi)M+MB_4O$7R5BGKpn0el7LMM8m>6}K_BBiD(`%XQ)IKattE`WXApi8z+DcH0*-tkkV&5=IpCQ?ZzI#8U-oA}MwkrQWK32SH=kU< zJ8v@P3^Jaj$fK75Zv$S2KUs+zy#)VXAt&fYKP2y>UUQmrqrV9PeH=Ui^~C& z^>7!wKuasg6!sO7C(m~x9EChzG>kz1qXM!SxBqd}&mq)>7EyJcsxM zGIb1i+xY(lUJl$oTzAvxhk`fHm**48`+hQ&E&eRf1GsDRZW8}@p^K!_P~i26=f~^U z3vmC4`tUa9^7oTc_7{@OE&&3F`xcoCn&i(5uxAR=#qg#cWN56sb z=-0r13OEx2LH`lxach{yHdL8zg2V3DQEp!SF$J~pX=6Kp-QYPj{=#y9i zY{SQ*KR|{z(Kg@0_=I^2&LHLDiDW5@Bb7qVvpAV_3TZiPMcD=MTe-hhX}S9_nTfIV zHk@Rd&g+7x6PTyqJZC9;9D4J*F_~nCMUv96E3nU_Bo+3|#=Ib%UP8LBk<73>$aezz z#-fe2qMpo$j&|tuZLC)SxI^kT(YL}4TSQEpUbRIS`6ZthUcZP{_5i>Gz^?Z7*8v{^ z{scc>)ELbIei<%aB)Z-PcQpWXqga=ZZUf+?!RSuFR>WiNd))#!0`QU31n<;9ra7o{ zd-!Vy@K<5a>uD?Pql5H2^cX!u-@yG!S8xMiGRwl@?kctx2N^QM`oado z9?>LfGBrh-KFwR24>VW8i^8kJo5L@Lf274ZTy2)NM7vDu&~|ILYah@a(VmE~MASzd zh`1DSH8LtPHL^MKLgXcU({zT;fb&ANx@MhEw^R3^?yyeQUDjR0y%>S0y-^QF9geyd zT^&6b{YdoFF;Yx!Odw`&%)ywUn30(CG4IEGg69#5v6-<&vBzT1#J(2$UhI`PZCr9( zR@@VDrzY*5bT&RYzBPU%{(SuVlWmh%Pi~+5(G)hNb;_YBm#17y$W5>%tWIc87)aQg za4=yg;c8-3Vp8Iq#Nx!7#C3@q6W>d`g4@(fr#?LO=+x(@zB2VX?xNGNk@{N zP8vx%pY;B;tZ60FmQ8a^>z=lK+TgT@ryZGgV%kf|9m$)McPAf6KAb$1d@}iT@`dDg zlRrqlHa&8B;&f@cVS3SY+w|J$%`+-y)Xi9zlAH2$YI16Nswwqo>WS2m+X`=c<+e9x z_RTy$^Ww~pX6>JKaMok9PRtsa^~$U_XT3k`qgmIaNGVa0q!HD=PE6?5z6uAAF2cVO<`xev}g zJa=gB$+@TJp35r9s>-U*a%6R8ZOc&IdVH zjR%d7&C|}SpLb^7YbMELFcq1qO{+~Vlg~6@+H3mQbln_fPBPCn8_mV$3iBoN$L8xe zFn=(2DEEcD)p@QwU*6Gtk{^?woS&X=%HNrPHvdBYyZImFUoFrS#22I%xC(p)0|k2v z9xQmQFtYHG!lQ*J3PGskG7L&!ri-#7!u=w2Kcgtp$ zJydqG>}=UvWgnDXFOM%zEjO0i$`6#kRes45Z<%drw*)M&SyQdeR-bjJb-(qp^_s2J zR%>(F0=B)jgSH`iy1lT1R8&+vRPkPAQDt>yb7gzw#mbMWSk;lL6IH)oQnaLc$rDRX zE%~sTR8Of+uP&^vs$N_DeDy0!HA|b9`j+lo`ry*XmR_mJuc@eMsOhNLTJvJfYc=oH zT)AW5j`Pcsm-Q{%x$NBX_~n-6kJL`7?Wlccg=59By3)Flm2741$^-S0^^W=rtEyHV zTAjK2k=1XliCMF`fi$dcxY*dzcw%kY+B0h}tbKp&l_pJ7VpDokev_@KzNw`t(6p!N zp{B>0PBfiqy3q7~)0O5K%~{RG&DG6on>(5Zng^Q?HNV*W#+^xbX5Q(#b7)=My8Y`8 zts7aNzy69N*-_%~IgU84IIEpIoyVMSI4`=GE7N6kt#++*`CLa`@3|x0M)z*_0rzS5 zCoP7SWi8Du`&;&V5jO;fsS`NKHl)khO3?F zoyDEII}dg~-FdaEs%wvr`O17%z6X3~{WJXQ{6F7VyzzrgWK&glXU~kD=0JMjt=@+= zM{Ta#+_(9}<~O$_Zdtu$q;F>5fqqMWb^qr6!~H}37y3UPm_6VcI6QE4;P-cB-L?C! zp}RiXn!HuoTDx^%>)_Ul+j6%xY}>tUXxoKt7q_Qwuirkj{lxYcx1Zg9en;Gn!X1M< z9@=qu$0s}Mced{A+j(_Y)UMQB#$AVYeSg>Y(c5Cez)qsS4kri24n#Wc+W9iVzZN$Y zt7i?cRJwX>|6z%eLj1;)C2BasyDj4ED8j?A&x7M|!1z0=)5uO0565$mudBEg&&3~8 z@kq>Jo>y@lXnv~V(HJ+*t9T6Xe^>EX@&LK2;(QLY4>{r%A>{TT=2!|&i4o(ef-@4w zTq+($EO`E;gyULEc1*>?F`s!?#kIu1K2`BZk`$Jy;yN-TtVG4})Cv1p3ZEF@TU9)k zN?}16;z+*cv>F~yB+Vx(KAFUXCt3X)`@6ku?Exv*WS%e8w|gXuv%Ay3MXK%gcX-?Z zsk}GP?(goA=ClU_8+(f9&1>@p+Iw9_x4&y%$Hu@smmr_3rn35dEgoNwr{xY$i?_GS zY|J+mEv&DzG%i#K#^Q4nf*X@bO7Ln=caPWalSKNPr>yVxx?KHIeg8&JwWr(D1yqCt z#S93a5c4KM_3hpsslx9INGtuVfi2E%kA#3uuUiN&^+JnoDFAD%Tv8(~-{|ov#5D?m zK^hm(Y=qUu({eV>%}#Hp)79ybw!l`BQ>rLmAvpuZ5*Gv(>~VK{HwJo)J>E{Ezq@VT z@`{>U$KcK>KaL3WlWuGTw~=-dAQEP*Cal8e1FJ`f2d)KgZgrDR&~AaR7Puehh&;qC z=*vkj+;)U@lODw5gd+R_@a@4~C}ykR>=hKfc=6hZRDRNh&<;=p;JQM%&%GfpE}xII zATJ-dd4Ngy3K@63$h8aasd>P?7qW2)&ETF7>5Irh$X*9tjle>s|17_p3H(B7C1IVv zm-}ku&UN+*DW#D7L;3upJnO;33oE!#4&3Jbu!{%xsd3&O=%|E_)7)s?KuG#=>wZ2e zUcz2cY865UUj8eAwW4IU2%GZqS13B+x*^ecN%X2^(+wJ4132wU^p`bomkTX?z{WY( zOyFQZ+|4Y=OHrwNH_JCDjgxGKd|pxVF8uPmx4_TkkPyT3Ehj4k9zZ>m#%iTfCwrg^ zw<)iKJ;;%lVkcZ)i`!5umm_`6|0qpp+25=Vh1OqnFMRY_w7Q%8Va&oqE9{u#j2HPC z9u#S4IK@RISTE?v%Q%=9O=D;*jUz5Pi9AK|-4d({-Q;PE9vOHe>2G9|w9o{aNNy+p zf%|Tf&^A5z9CR( zw1aNJYOEi%yo-E?*ij>{Q$qZ7fZm03KbLVW6U8B@jdUB%OLfy7bSK?KcVjQDhwi}+ z%_h2+eu?g*_hLPFA9it;piTdkewiMi_tOW+Qu-C#7yDJzv0sw_eF(LA3qCpdFzKaV zrw4IE>mlp|-9aD0j@UBno-C)|#+vX^jQ#%y{qG9;UHTaI{rb?y^65%5KSNbmfH!?zgOy9$) zi}&fj(@XSsSmXW&y-fc=KcN3fKcs)8AJIS2kLiEWEA-Fw6Z#i=mHw4}O8=W)!+GB8 zbQH}2k1FvflONF5;>Nc~96^o3O@uMHR4tB8V)1M;!}Bbb$fmL+HVv!i>1+l|VX3$y zZ6=$=B$mczGd)XZ87vd`^v_{)vA)j6oxVBDi1Q65W@foKDVom;u)3kcU{2;@Zq~v)td+H~cIIUrYy<0L zUChV)Y$Mymx>*kkuwJ$q=N zFYz%JcC*4 z3GyuVG=4z-i42h!vHKoQqSzq2kL}0K$B%FV@ypl|`3t#+9l(y*!|Va<#mA99l8?wK z^tbn8jywyyZx4~LlJ8+A>_mV3AbEs6$i7Mr;T@32*+ZC(N8;Jlb9g$SBm2l+avvEa z`^nw-;?BdEU;m!$W?v_#*+KRVc8GnGJ;J`l4zq8w@32SN5%yj77<-&O!M?|i;)CQv z>`C^0_7r=XJ;P)+%#N|+nBl)o{*7EDZ;}IeN@gYhO5Va#gWr>Y7wHS9SBbYcgAHioaa=kt!{6(ySJ;g)6*AaZSe=3ZcG~kTASMm zDmdMKXFzKgKF-UOo2&A+sIpqsJgsUTR#jGOew2NTpCX1On6x~?u8Lt-#8Bg{(Ul?M zRE{OrRJokp(N*Jd3cXcT&sr3*MCG?c;ip{^@OHL%qN~S~XltDA-hfA2Gp>s{&!SzX zgf0`IVRm1e!rG>4V^c-8san}oi`#-)tCqLg!aFL@Zat*VZZ0)G5|qDSXi@$CcphP3EEsO+5^vtyjoah14LsDxbYDeAT!- zc2$cCRV#Z?K2wW7=q2lv45thciJNQkhy*A+2g=R+YI`71CM|Nl{OFExb|TDdU!d(&s(k0TdCYlMO(z7?`jjZ2 zhzj$d2Kqxv*rpoGrdq_N8qKDbq%CMvwM4BI;r{U^VN>O{2UDq3Hnm9X=2-uPCgE39 zi}v?)I(ym`$+}fX2&nB5zUZEDB{c!wOan@E@0jc+Tu-7{&#ua9pC8^kE}LD|s6y4y z9+Xv;(OwbTJ3+Qy)$F2o$Q2r);RyZFaMT7@i5qSaQ#@yI3XtBsxBHfL1p`quTRfI+lVppk9sI~2sLA{wW$$E|aU90ev!4=hSp z$Z7`~=Ny+E-WX?4H<3W-z!RvAT%d}TfJQpGp#-6@6|iup2frE@|8ese_gL<3QT_;v z#@O28?d;^z#g6w7JV^_Fw4Oja9G%i(C>S4pc|2#X^Ng`nIunEmh0vb>jq^-Y2w5q8 zGU8&#yAi=?Og*&^;hfZN1gNH!{|NosCR#2x4>7Uhy#}Y_GDq-UgL}OA(RqV%#(5`- z)n{zhOEMJ^DQz%HCyr}RPs3(}xV8mo6og)#FA zqv16xf_G7zTIr>LDRwL5C9M)$fNFXE~hnV={*HPCR9QsEkT4#S;ziL`v@@ zu%Ojq$Ga+oi}5ONf#|nQdCIK7lxML<40yWz#z3nUvuW-Gws0Q`uiL}@5v~5-ZsB@2 zi})UIACK?BoZrV058trn1U|1|pcDLBeEzOT&QTzoCr6?bt{l|~z6!=U3p&nQ&?(#n zs_++tA_swqJbb-f-69Wx@H{x8=D|@V4+Z0S2s)mJpi}Y?sFH^u6nSt=*vn*5#u$@D znT41vV(iH^%@=lrE5<*#VvK?-#tXP&QU`Z|4ptES+hc_G3f>dl3W-!aMu?(%lzf$0 z93BIhrnL8OZ1?!qD~=c@I7#k&Wst=YJCnxV+wB*DCX1LD=b9{Hq|H^wNVtle=3GV2 zT$3`Unk)s{F0YR-D|$R`JT4Gi%;r3urze0eEZ}L;qW{JaCdA4`brA!dMGWYsT&rT9 zJd-kq%`?r{i3*M95iXsm#vBuA@=QvaJd)&%xZeGG7ZQxTVgOIyF7SKGESuEX~Lm>C39ubXUfYHc7UtspQp|-^74wr2o8EN zb_cr~K8|yRAtXQ<_icIK512 z8$6B2k|?Llku?T6EL)yxZQ%LINmi>$kRr86@<^?$$y|F3Z&F$9Zo90tH>Am78I5&K z4IoY#Y>?#IS_G9frbu!T$BG&orD25{63s!7>XT#>k2i73k=h0c));h3{FZD7LL?p+ z#j!$;6*^KJxPLkY){x#WHs~AE8YQ`GWdq_;xLs6H za^whutg~hx!v?&tdL+DhiyqZQZ*j`Z)hbgr1d$`Ma%7!B;?l-JEe&yj1oD zCZvrr9Mi=StKE{7Hdb+>4HGL;jKYOxLj)^ScS!a@y^|NJFg8iy1tLo+5HctwidOHm zDOtqcBDtK7R7gCgT4T(Wf&5mK?%w6+*b!*yeO~9U=%NmBEbf32rf^yI;25|Bu|Ffa^xw7rS%QNnigAQx*Y4# z_vOe5hNUYSmabF+Q_>KgAi@(3!(@teRm1R@7#YBWSAj1!m@wVb*Z2DR(7H)||2!gob z#K>&7BgULR3ci`JOfOe?2yp=Q3tOaPPnp>S6-7ro|i4pL&G$qO;n=l-n3=voke=y!~b0h z)XN+>H(1ugaaudCda^ldIGj$kH=uXqrI;6Do?Fr68>9juc>%a7eC(g?FVGF$R9YTR zl9U6nwo-l3a6X;NbuENFpukPjIM8aGMLF_(gK=6(j$HJQNKwPxAYXtYB1svNQL5y9 z15CSQaIjKeiN2@-BOtn83{6FpPECY`i_wWC$}R{Hk5*cwVS1B|%$AkRUu$wS~R}W?D2BB}btTk)#TJ zCC`+XVrei=D5F?fCiM+QsRScCm!2tsU^-S5vNi+0C5RfE#3+UM*_!9jtEGh@AV*#t z%uQHdEiMP2>D;Jtu!zghe;BzHE97a`hT0Siu2M;(ao9u?(QeBp#MY(MPKdQkhz+I< z<#%HWt3fW#4kZXC3T9|C$P2RvQT=!w8$?ULm247<72;7d8L?tx8wktb+YdYB9Gr@5f5?MJZ_^^(C!Qm9r8ZaB+6f zDpl|;%ueHF#_ghNGiHJ%Fu_!%*<+f57M@^~3(?A}ZxOx}>}XfMJ<%VN~Q~;?3LOHU+aEywOIv^rsC8w!GR6VER$SO|5k=2}r zBWn!D2_aTs4ZtwS18X!K$3uFKtp%opHE}x1!f)-L4Ym{-Wfu?`^@$2JJLIMylT;#ilE zi(@_^7svdtamiQ#ZWKPb3=x|Yv>a$RH##SiE%5bVtOd$x0t(7$dIb%S;53_&c+nWw zEy5>K^eHG$(XXJKd;okFDJ<_&P)@K_K{>%T(3Xzz+b(>9-wp-kHD<~(}1KP!7{O%Dx!EdjEa`G=JC@0^Cl#3O9_bMnS7*tSBaG&8=w3y<`+7z6g z4YOnQgt4sAk}XGiMmXpL@K+?iV7Wb6J zRBMVOjoM62azuEP8nldAwE3DWHY;2N#aLdPG7>j}Zzqpv%kT(28f23#FOssce;)Q6 z2_wWdoKE+xz{+7?1NXPshUakqsYs#(5L;u)@a;V4`N*AkBeZOvyIxQtLVWxuriPVh jO`16j-%O9oIz>nCku_h&SZ+HW-h#WRY+Nxk6#V^PlES5E diff --git a/src/ClawdDotNet.Desktop/Assets/Fonts/BarlowCondensed-Regular.ttf b/src/ClawdDotNet.Desktop/Assets/Fonts/BarlowCondensed-Regular.ttf deleted file mode 100644 index ecbe0cc84118decc6a16216ad53d83d39888b175..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 102480 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�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 Assets\app.ico - - true - + WinExe verhaelt sich dort ohnehin wie Exe. #764: Seit die Fenster entfernt sind, + heisst das unter Windows: Der Starter (ohne Schalter) blitzt nicht als Konsole auf. --> false - - - - - - - - - - - - - - - + @@ -42,13 +24,6 @@ - - - - PreserveNewest - - - @@ -56,7 +31,10 @@ warum das so sein muss, steht in ClawdDotNet.Web/WebUiHost.cs. Die Richtung des Verweises ist Absicht: Desktop kennt Web, Web kennt Desktop - nicht. Wer hier umdreht, hat den Schnitt verletzt. --> + nicht. Wer hier umdreht, hat den Schnitt verletzt. + + #764: Seit die Fenster entfernt sind, ist der Instanzprozess (HeadlessRun) der + einzige Wirt; die HTTP-Flaeche ist sein Zugang fuer Manager und Weboberflaeche. --> diff --git a/src/ClawdDotNet.Desktop/Controls/BlueprintFrame.cs b/src/ClawdDotNet.Desktop/Controls/BlueprintFrame.cs deleted file mode 100644 index 0f79b59..0000000 --- a/src/ClawdDotNet.Desktop/Controls/BlueprintFrame.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Avalonia.Controls; -using Avalonia.Controls.Primitives; - -namespace ClawdDotNet.Desktop.Controls; - -///

-/// Der Rahmen mit den vier Eckmarken — das wiederkehrende Motiv des Entwurfs. -/// -/// Eigenes Steuerelement statt vier von Hand gesetzter Striche je Stelle: Die Marken -/// liegen bewusst halb außerhalb des Rahmens, und das ist genau die Sorte Detail, -/// die beim Nachbauen an der fünften Stelle nicht mehr stimmt. -/// -/// Weil die Marken über den Rand hinausragen, darf kein Elternteil zuschneiden. -/// In der Praxis heißt das: nicht direkt an den Fensterrand setzen, sondern mit etwas -/// Abstand — die Vorlage im Entwurf tut dasselbe. -/// -/// Sparsam verwenden. Im Entwurf tragen nur die Info-Karte und die beiden Dialoge -/// die Marken; alle übrigen Karten sind schlichte Haarlinien-Kästen (Klasse -/// card in Styles/Shell.axaml). -/// -public sealed class BlueprintFrame : ContentControl -{ - protected override Type StyleKeyOverride => typeof(BlueprintFrame); -} diff --git a/src/ClawdDotNet.Desktop/Controls/StrokeIcon.cs b/src/ClawdDotNet.Desktop/Controls/StrokeIcon.cs deleted file mode 100644 index 5b31636..0000000 --- a/src/ClawdDotNet.Desktop/Controls/StrokeIcon.cs +++ /dev/null @@ -1,113 +0,0 @@ -using Avalonia; -using Avalonia.Controls; -using Avalonia.Controls.Documents; -using Avalonia.Media; - -namespace ClawdDotNet.Desktop.Controls; - -/// -/// Ein Strichsymbol aus dem Entwurf — 24×24-Geometrie, gezeichnet mit der geerbten -/// Vordergrundfarbe. -/// -/// Warum nicht PathIcon: Das füllt seine Geometrie. Die Symbole des Entwurfs -/// sind Umrisse (Lucide, Strichstärke 1.5); gefüllt werden daraus schwarze Klumpen. -/// -/// Warum nicht Path mit Stroke: Dann müsste an jeder einzelnen Stelle -/// die Farbe mitgegeben werden — und zwar die richtige, je nachdem ob das Symbol -/// in einer Schaltfläche, einer ausgewählten Navigationszeile oder der Statusleiste sitzt. -/// ist hier von übernommen und erbt -/// daher wie eine Textfarbe: Wer den Text einfärbt, färbt das Symbol mit. -/// -/// Die Strichstärke wird beim Skalieren mitskaliert. Das ist keine Nachlässigkeit, -/// sondern das Verhalten von SVG: stroke-width zählt in Einheiten des viewBox. -/// Ein Symbol mit 1.5 in 24×24, dargestellt auf 16 px, hat genau 1 px starke Linien. -/// -public sealed class StrokeIcon : Control -{ - /// Kantenlänge des Koordinatenraums aller Symbole (SVG-viewBox 0 0 24 24). - private const double ViewBox = 24d; - - public static readonly StyledProperty DataProperty = - AvaloniaProperty.Register(nameof(Data)); - - /// Geerbt wie eine Textfarbe — siehe Klassenbeschreibung. - public static readonly StyledProperty ForegroundProperty = - TextElement.ForegroundProperty.AddOwner(); - - public static readonly StyledProperty StrokeThicknessProperty = - AvaloniaProperty.Register(nameof(StrokeThickness), 1.5d); - - /// Für die wenigen massiven Symbole des Entwurfs (Wiedergabe, Halt). - public static readonly StyledProperty IsFilledProperty = - AvaloniaProperty.Register(nameof(IsFilled)); - - static StrokeIcon() - { - AffectsRender( - DataProperty, ForegroundProperty, StrokeThicknessProperty, IsFilledProperty); - AffectsMeasure(DataProperty); - } - - public Geometry? Data - { - get => GetValue(DataProperty); - set => SetValue(DataProperty, value); - } - - public IBrush? Foreground - { - get => GetValue(ForegroundProperty); - set => SetValue(ForegroundProperty, value); - } - - public double StrokeThickness - { - get => GetValue(StrokeThicknessProperty); - set => SetValue(StrokeThicknessProperty, value); - } - - public bool IsFilled - { - get => GetValue(IsFilledProperty); - set => SetValue(IsFilledProperty, value); - } - - /// - /// Ohne gesetzte Größe 16×16 — die Größe, in der die meisten Symbole im Entwurf stehen. - /// Ein unbegrenzter Vorschlag würde das Symbol den ganzen Platz nehmen lassen. - /// - protected override Size MeasureOverride(Size availableSize) - { - var width = double.IsInfinity(availableSize.Width) ? 16d : Math.Min(16d, availableSize.Width); - var height = double.IsInfinity(availableSize.Height) ? 16d : Math.Min(16d, availableSize.Height); - return new Size(width, height); - } - - public override void Render(DrawingContext context) - { - if (Data is not { } geometry || Foreground is not { } brush) return; - - var scale = Math.Min(Bounds.Width / ViewBox, Bounds.Height / ViewBox); - if (scale <= 0) return; - - // Mittig setzen, falls das Steuerelement nicht quadratisch ist. - var offsetX = (Bounds.Width - ViewBox * scale) / 2; - var offsetY = (Bounds.Height - ViewBox * scale) / 2; - - using var _ = context.PushTransform( - Matrix.CreateScale(scale, scale) * Matrix.CreateTranslation(offsetX, offsetY)); - - if (IsFilled) - { - context.DrawGeometry(brush, null, geometry); - return; - } - - // Runde Enden und Verbindungen: Ohne sie verschwinden die Punkt-Symbole - // (Pfadstücke der Länge 0.01, etwa in „Agenten-Chats") vollständig. - var pen = new Pen(brush, StrokeThickness, - lineCap: PenLineCap.Round, lineJoin: PenLineJoin.Round); - - context.DrawGeometry(null, pen, geometry); - } -} diff --git a/src/ClawdDotNet.Desktop/Converters/IconConverter.cs b/src/ClawdDotNet.Desktop/Converters/IconConverter.cs deleted file mode 100644 index ffc25b7..0000000 --- a/src/ClawdDotNet.Desktop/Converters/IconConverter.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System.Globalization; -using Avalonia; -using Avalonia.Controls; -using Avalonia.Data.Converters; -using Avalonia.Media; - -namespace ClawdDotNet.Desktop.Converters; - -/// -/// Schlägt eine Symbol-Geometrie aus Styles/Icons.axaml über ihren Namen nach. -/// -/// Damit halten die Ansichtsmodelle nur den Namen („IconChat") statt einer -/// — sie brauchen dann keinen Verweis auf Avalonia.Media, -/// und die Navigationsleiste kommt mit einer schlichten Zeichenkette je Eintrag aus. -/// -/// Dass hier keine Themenumschaltung nötig ist, ist kein Zufall: Die Geometrien sind -/// themenunabhängig, gefärbt wird erst beim Zeichnen über die geerbte Vordergrundfarbe -/// (siehe Controls/StrokeIcon.cs). Für Farben wäre dieser Weg falsch — ein einmal -/// aufgelöster Pinsel bliebe beim Wechsel auf Dunkel stehen. -/// -public sealed class IconConverter : IValueConverter -{ - public static readonly IconConverter Instance = new(); - - public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) - { - if (value is not string key || string.IsNullOrEmpty(key)) return null; - if (Application.Current is not { } app) return null; - - return app.TryFindResource(key, out var resource) ? resource as Geometry : null; - } - - public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) - => throw new NotSupportedException("Nur zur Anzeige."); -} - -/// -/// Der Pfeil am Einklapp-Schalter der Seitenleiste: zeigt nach links, solange -/// eingeklappt werden kann, und nach rechts, wenn wieder aufgeklappt wird. -/// -public sealed class SidebarChevronConverter : IValueConverter -{ - public static readonly SidebarChevronConverter Instance = new(); - - public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) - { - var isCollapsed = value is true; - return IconConverter.Instance.Convert( - isCollapsed ? "IconChevronRight" : "IconChevronLeft", targetType, parameter, culture); - } - - public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) - => throw new NotSupportedException("Nur zur Anzeige."); -} diff --git a/src/ClawdDotNet.Desktop/Converters/LayoutConverters.cs b/src/ClawdDotNet.Desktop/Converters/LayoutConverters.cs deleted file mode 100644 index d452b5f..0000000 --- a/src/ClawdDotNet.Desktop/Converters/LayoutConverters.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System.Globalization; -using Avalonia.Data.Converters; -using Avalonia.Layout; - -namespace ClawdDotNet.Desktop.Converters; - -/// -/// Richtet Sprechblasen aus: rechts fuer den Benutzer, links fuer den Agenten. -/// -/// Ausrichtung und nicht Farbe — deshalb ist ein Konverter hier richtig. Der -/// frueher danebenstehende ChatBubbleBrushConverter lieferte einen Pinsel mit festem -/// Farbwert und ueberlebte den Themenwechsel nicht; die Hinterlegung eigener Nachrichten -/// laeuft jetzt ueber die Stilklasse card accent. -/// -public sealed class ChatAlignmentConverter : IValueConverter -{ - public static readonly ChatAlignmentConverter Instance = new(); - - public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) - => value is true ? HorizontalAlignment.Right : HorizontalAlignment.Left; - - public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) - => throw new NotSupportedException("Nur zur Anzeige."); -} - -/// -/// Prueft, ob ein Werkzeugname mit dem ConverterParameter uebereinstimmt. -/// Blendet im Werkzeug-Einstellungsbereich die passende Feldgruppe ein. -/// -public sealed class ToolMatchConverter : IValueConverter -{ - public static readonly ToolMatchConverter Instance = new(); - - public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) - => value is string toolName && parameter is string targetTool - && toolName.Equals(targetTool, StringComparison.OrdinalIgnoreCase); - - public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) - => throw new NotSupportedException("Nur zur Anzeige."); -} diff --git a/src/ClawdDotNet.Desktop/Converters/StringEqualsConverter.cs b/src/ClawdDotNet.Desktop/Converters/StringEqualsConverter.cs deleted file mode 100644 index 36930eb..0000000 --- a/src/ClawdDotNet.Desktop/Converters/StringEqualsConverter.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.Globalization; -using Avalonia.Data.Converters; - -namespace ClawdDotNet.Desktop.Converters; - -/// -/// Vergleicht eine Zeichenkette mit dem ConverterParameter, ohne Gross- und -/// Kleinschreibung zu unterscheiden. -/// -/// Gedacht fuer Classes.xyz="{Binding …}": Die Ansicht setzt damit eine -/// Stilklasse, und die Farbe dazu steht in Styles/Shell.axaml an -/// DynamicResource. Das ersetzt den frueheren LogLevelBrushConverter, der -/// Pinsel mit festen Farbwerten zurueckgab — die blieben beim Wechsel auf Dunkel -/// unveraendert stehen, weil ein einmal gelieferter Pinsel nichts mehr vom Thema -/// mitbekommt. -/// -public sealed class StringEqualsConverter : IValueConverter -{ - public static readonly StringEqualsConverter Instance = new(); - - public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) - => value is string text && parameter is string expected - && text.Equals(expected, StringComparison.OrdinalIgnoreCase); - - public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) - => throw new NotSupportedException("Nur zur Anzeige."); -} diff --git a/src/ClawdDotNet.Desktop/LauncherRun.cs b/src/ClawdDotNet.Desktop/LauncherRun.cs new file mode 100644 index 0000000..3b35a4b --- /dev/null +++ b/src/ClawdDotNet.Desktop/LauncherRun.cs @@ -0,0 +1,180 @@ +using System.Diagnostics; +using System.Net.Sockets; +using System.Text.Json; +using ClawdDotNet.Core.Storage; + +namespace ClawdDotNet.Desktop; + +/// +/// #764: ClawdDotNet started without a switch — by a double click, a start menu entry, +/// a desktop file. +/// +/// Until #764 that opened the Avalonia window. The windows are gone; the web interface is +/// the only one. What a person who starts the program wants is therefore: the instance manager +/// running, and its web interface in front of them. Until the shell with its own window exists +/// (#764, stage 2) the system browser shows it. +/// +/// Never a second manager. If the manager answers, it is left alone. If it runs as +/// a systemd service on this machine, the service is started — starting the program next to it +/// would put two managers on the same instances. Only otherwise is the manager program started +/// directly. +/// +internal static class LauncherRun +{ + private const int ExitOk = 0; + private const int ExitNoManager = 6; + + private const int DefaultPort = 7000; + private const string ServiceUnit = "clawddotnet-manager.service"; + private static readonly TimeSpan StartWait = TimeSpan.FromSeconds(30); + + public static async Task RunAsync() + { + var port = ManagerPort(); + + if (!Answers(port)) + { + var problem = StartManager(); + if (problem is not null) + { + await Console.Error.WriteLineAsync(problem); + return ExitNoManager; + } + + var until = DateTime.UtcNow + StartWait; + while (!Answers(port) && DateTime.UtcNow < until) + await Task.Delay(500); + + if (!Answers(port)) + { + await Console.Error.WriteLineAsync( + $"The instance manager did not answer on port {port} within {StartWait.TotalSeconds:0} s. " + + "Its log is under Logs/Manager in the data directory."); + return ExitNoManager; + } + } + + var url = $"http://localhost:{port}/"; + Console.WriteLine(url); + SystemShell.OpenUrl(url); + return ExitOk; + } + + /// Why the manager could not be started, or null. + private static string? StartManager() + { + if (OperatingSystem.IsLinux() && Systemctl("cat", ServiceUnit) == 0) + { + return Systemctl("start", ServiceUnit) == 0 + ? null + : $"systemctl --user start {ServiceUnit} failed; see journalctl --user -u {ServiceUnit}."; + } + + if (FindManagerExecutable() is not { } manager) + { + return "The instance manager (ClawdDotNet.Instanzmanager) was not found next to this program."; + } + + try + { + // On Windows with its own console window: that is where the manager shows the access + // token on first start. Elsewhere a plain child that outlives us. + Process.Start(new ProcessStartInfo(manager) + { + UseShellExecute = OperatingSystem.IsWindows(), + WorkingDirectory = Path.GetDirectoryName(manager)! + }); + return null; + } + catch (Exception ex) + { + return $"The instance manager could not be started: {ex.Message}"; + } + } + + private static bool Answers(int port) + { + try + { + using var client = new TcpClient(); + return client.ConnectAsync("127.0.0.1", port).Wait(TimeSpan.FromSeconds(1)) && client.Connected; + } + catch (Exception) + { + return false; + } + } + + private static int Systemctl(string verb, string unit) + { + try + { + var start = new ProcessStartInfo("systemctl") { RedirectStandardOutput = true, RedirectStandardError = true }; + start.ArgumentList.Add("--user"); + start.ArgumentList.Add(verb); + start.ArgumentList.Add(unit); + using var p = Process.Start(start)!; + p.StandardOutput.ReadToEnd(); + p.StandardError.ReadToEnd(); + p.WaitForExit(30_000); + return p.HasExited ? p.ExitCode : -1; + } + catch (Exception) + { + return -1; // no systemd here + } + } + + /// + /// Next to this program in an installation; the build folders in a development checkout. + /// + /// Built from segments, not as a string: a path with backslashes is one file name on + /// Linux, and the search never found anything there (moved here from App.axaml.cs). + /// + private static string? FindManagerExecutable() + { + var name = OperatingSystem.IsWindows() ? "ClawdDotNet.Instanzmanager.exe" : "ClawdDotNet.Instanzmanager"; + + var nextTo = Path.Combine(AppContext.BaseDirectory, name); + if (File.Exists(nextTo)) return nextTo; + + string[][] developmentPaths = + [ + ["..", "..", "..", "..", "ClawdDotNet.ManagerApp", "bin", "Debug", "net10.0"], + ["..", "..", "..", "..", "..", "src", "ClawdDotNet.ManagerApp", "bin", "Debug", "net10.0"] + ]; + + foreach (var segments in developmentPaths) + { + var path = Path.GetFullPath(Path.Combine([AppContext.BaseDirectory, .. segments, name])); + if (File.Exists(path)) return path; + } + + return null; + } + + /// + /// The port from manager.json; the default on any doubt. Read as one field, not as + /// the manager's settings type, which this program does not know. + /// + private static int ManagerPort() + { + try + { + var file = Path.Combine(AppPaths.ConfigDirectory, "manager.json"); + if (!File.Exists(file)) return DefaultPort; + + using var doc = JsonDocument.Parse(File.ReadAllText(file)); + return doc.RootElement.TryGetProperty("webUiPort", out var port) + && port.ValueKind == JsonValueKind.Number + && port.TryGetInt32(out var value) + && value is > 0 and < 65536 + ? value + : DefaultPort; + } + catch (Exception) + { + return DefaultPort; + } + } +} diff --git a/src/ClawdDotNet.Desktop/Program.cs b/src/ClawdDotNet.Desktop/Program.cs index b3fddfe..c0ba1e8 100644 --- a/src/ClawdDotNet.Desktop/Program.cs +++ b/src/ClawdDotNet.Desktop/Program.cs @@ -1,25 +1,21 @@ -using Avalonia; - namespace ClawdDotNet.Desktop; internal static class Program { /// - /// Einstiegspunkt der Oberfläche. + /// Einstiegspunkt. /// - /// Bewusst schlank: Hier wird nur Avalonia hochgefahren. Alles Fachliche — - /// Einstellungen, Instanzauswahl, Engine, Scanner, Watchdog — baut - /// über die Anwendungsschicht auf, damit derselbe Aufbau später - /// auch ohne Fenster laufen kann. + /// #764: Bis hierher fuhr ohne Schalter die Avalonia-Oberfläche hoch. Die Fenster + /// sind entfernt — die Weboberfläche ist die einzige Oberfläche. Die Programmdatei bleibt, + /// was sie für den Betrieb immer war: der Instanzprozess (--headless --managed + /// --instance …, so startet der Manager jede Instanz), die MCP-Brücke und der Starter + /// in der Sandbox. Ohne Schalter startet sie den Instanzmanager, falls er nicht läuft, und + /// öffnet die Weboberfläche (). /// - /// Kein [STAThread] mehr: Das war eine COM-Anforderung von WinForms. Avalonia - /// braucht es nicht, und unter Linux hätte es ohnehin keine Bedeutung. + /// Kein Fenstersystem wird angefasst — auf einem Server ohne Bildschirmsitzung gäbe + /// es keines (#528, Stufe 2). Das galt bisher für --headless und gilt jetzt für + /// alles. /// - /// - /// Die Verzweigung steht vor und nicht darin: Mit - /// --headless soll gar kein Fenstersystem angefasst werden — auf einem Server - /// ohne Bildschirmsitzung gäbe es keines (#528, Stufe 2). - /// public static int Main(string[] args) => CommandLine.IsSandboxLaunch(args) ? Core.Sandbox.SandboxLauncher.RunAsync(args).GetAwaiter().GetResult() @@ -27,19 +23,5 @@ internal static class Program ? McpBridgeRun.RunAsync(args).GetAwaiter().GetResult() : CommandLine.IsHeadless(args) ? HeadlessRun.RunAsync(args).GetAwaiter().GetResult() - : BuildAvaloniaApp().StartWithClassicDesktopLifetime(args); - - /// - /// Auch vom Vorschau-Werkzeug des Editors aufgerufen — deshalb öffentlich und - /// getrennt von . - /// - public static AppBuilder BuildAvaloniaApp() - => AppBuilder.Configure() - .UsePlatformDetect() - // Kein WithInterFont mehr: Die Oberfläche bringt seit dem Umbau auf den - // Entwurf Barlow und Barlow Condensed als eigene Ressourcen mit - // (Assets/Fonts, referenziert in Styles/Theme.axaml). Der Grund von damals - // gilt unverändert — ein schlankes Linux-Abbild hat oft gar keine - // Systemschrift —, nur liegt die mitgelieferte Schrift jetzt woanders. - .LogToTrace(); + : LauncherRun.RunAsync().GetAwaiter().GetResult(); } diff --git a/src/ClawdDotNet.Desktop/Services/AvaloniaLicensePrompt.cs b/src/ClawdDotNet.Desktop/Services/AvaloniaLicensePrompt.cs deleted file mode 100644 index 573fcd7..0000000 --- a/src/ClawdDotNet.Desktop/Services/AvaloniaLicensePrompt.cs +++ /dev/null @@ -1,86 +0,0 @@ -using Avalonia.Controls; -using Avalonia.Threading; -using ClawdDotNet.App.Services; -using ClawdDotNet.Desktop.ViewModels; -using ClawdDotNet.Desktop.Views; -using ClawdDotNet.Licensing; - -namespace ClawdDotNet.Desktop.Services; - -/// -/// Lizenzabfrage über Fenster. -/// -/// Der Aufbau läuft auf einem Hintergrundfaden — Avalonia besteht aber darauf, dass -/// Fenster auf dem Oberflächenfaden entstehen. Deshalb geht hier alles über -/// . Das ist der Grund, warum -/// durchgehend asynchron ist: Die WinForms-Fassung konnte -/// ShowDialog einfach blockierend aufrufen, weil sie ohnehin auf dem -/// Oberflächenfaden lief. -/// -public sealed class AvaloniaLicensePrompt : ILicensePrompt -{ - public async Task RequestKeyAsync(string hardwareId, string? problem, string? currentKey) - => await Dispatcher.UIThread.InvokeAsync(async () => - { - var viewModel = new LicenseViewModel(hardwareId, problem, currentKey); - var window = new LicenseWindow { DataContext = viewModel }; - - window.Show(); - - var key = await viewModel.Result; - window.Close(); - - return key; - }); - - public Task ShowInfoAsync(string title, string message) - => ShowMessageAsync(title, message); - - public Task ShowErrorAsync(string title, string message) - => ShowMessageAsync(title, message); - - /// - /// Ein Meldungsfenster. - /// - /// Avalonia bringt kein MessageBox mit — bewusst, weil es auf allen - /// Plattformen anders aussähe. Ein schlichtes Fenster ist hier ausreichend und - /// erspart uns eine weitere Abhängigkeit für drei Aufrufstellen. - /// - private static async Task ShowMessageAsync(string title, string message) - => await Dispatcher.UIThread.InvokeAsync(async () => - { - var completion = new TaskCompletionSource(); - - var button = new Button - { - Content = "OK", - HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Right, - IsDefault = true - }; - - var window = new Window - { - Title = title, - Width = 460, - SizeToContent = SizeToContent.Height, - CanResize = false, - WindowStartupLocation = WindowStartupLocation.CenterScreen, - Content = new StackPanel - { - Margin = new Avalonia.Thickness(20), - Spacing = 16, - Children = - { - new TextBlock { Text = message, TextWrapping = Avalonia.Media.TextWrapping.Wrap }, - button - } - } - }; - - button.Click += (_, _) => window.Close(); - window.Closed += (_, _) => completion.TrySetResult(); - - window.Show(); - await completion.Task; - }); -} diff --git a/src/ClawdDotNet.Desktop/Services/LocalizationManager.cs b/src/ClawdDotNet.Desktop/Services/LocalizationManager.cs deleted file mode 100644 index c64bb3c..0000000 --- a/src/ClawdDotNet.Desktop/Services/LocalizationManager.cs +++ /dev/null @@ -1,199 +0,0 @@ -using System.ComponentModel; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Text.Json; - -namespace ClawdDotNet.Desktop.Services; - -public sealed record LanguageOption(string Code, string Name) -{ - public override string ToString() => Name; -} - -/// -/// Manages application localization for Avalonia UI. -/// Supports JSON language packs with fallback to English, dynamic language switching, -/// and live UI re-binding via indexer property notification. -/// -public sealed class LocalizationManager : INotifyPropertyChanged -{ - public static LocalizationManager Instance { get; } = new(); - - public const string DefaultLanguage = "en"; - public const string FallbackLanguage = "en"; - - private readonly Dictionary _fallbackStrings = new(StringComparer.OrdinalIgnoreCase); - private Dictionary _activeStrings = new(StringComparer.OrdinalIgnoreCase); - private string _currentLanguage = DefaultLanguage; - - public IReadOnlyList AvailableLanguages { get; } = - [ - new("en", "English"), - new("de", "Deutsch") - ]; - - public event PropertyChangedEventHandler? PropertyChanged; - public event Action? LanguageChanged; - - public string CurrentLanguage - { - get => _currentLanguage; - private set - { - if (_currentLanguage != value) - { - _currentLanguage = value; - OnPropertyChanged(); - } - } - } - - [IndexerName("Item")] - public string this[string key] => Get(key); - - private LocalizationManager() - { - LoadFallbackPack(); - SetLanguage(DefaultLanguage); - } - - private void LoadFallbackPack() - { - _fallbackStrings.Clear(); - var json = LoadLanguageJson(FallbackLanguage); - if (!string.IsNullOrWhiteSpace(json)) - { - ParseJsonIntoDictionary(json, _fallbackStrings); - } - } - - public void SetLanguage(string? languageCode) - { - var target = string.IsNullOrWhiteSpace(languageCode) ? DefaultLanguage : languageCode.Trim().ToLowerInvariant(); - - if (target == FallbackLanguage) - { - _activeStrings = _fallbackStrings; - } - else - { - var pack = new Dictionary(StringComparer.OrdinalIgnoreCase); - var json = LoadLanguageJson(target); - if (!string.IsNullOrWhiteSpace(json)) - { - ParseJsonIntoDictionary(json, pack); - } - _activeStrings = pack; - } - - CurrentLanguage = target; - - // Notify indexer bindings so Avalonia refreshes all localized strings on screen - OnPropertyChanged("Item"); - OnPropertyChanged("Item[]"); - LanguageChanged?.Invoke(); - } - - public string Get(string key, params object[] args) - { - if (string.IsNullOrEmpty(key)) return ""; - - string? template = null; - if (!_activeStrings.TryGetValue(key, out template)) - { - _fallbackStrings.TryGetValue(key, out template); - } - - template ??= key; - - if (args.Length > 0) - { - try - { - return string.Format(template, args); - } - catch - { - return template; - } - } - - return template; - } - - private static string? LoadLanguageJson(string langCode) - { - // 1. Try file on disk in AppContext.BaseDirectory/i18n/{langCode}.json - var localPath = Path.Combine(AppContext.BaseDirectory, "i18n", $"{langCode}.json"); - if (File.Exists(localPath)) - { - try - { - return File.ReadAllText(localPath); - } - catch - { - // Fall through to embedded resource - } - } - - // 2. Try embedded resource in ClawdDotNet assembly - var assembly = Assembly.GetExecutingAssembly(); - var resourceName = assembly.GetManifestResourceNames() - .FirstOrDefault(r => r.EndsWith($"i18n.{langCode}.json", StringComparison.OrdinalIgnoreCase)); - - if (resourceName is not null) - { - using var stream = assembly.GetManifestResourceStream(resourceName); - if (stream is not null) - { - using var reader = new StreamReader(stream); - return reader.ReadToEnd(); - } - } - - return null; - } - - private static void ParseJsonIntoDictionary(string json, Dictionary dict) - { - try - { - using var doc = JsonDocument.Parse(json); - FlattenElement("", doc.RootElement, dict); - } - catch - { - // Invalid JSON ignored - } - } - - private static void FlattenElement(string prefix, JsonElement element, Dictionary dict) - { - switch (element.ValueKind) - { - case JsonValueKind.Object: - foreach (var prop in element.EnumerateObject()) - { - var childPrefix = string.IsNullOrEmpty(prefix) ? prop.Name : $"{prefix}.{prop.Name}"; - FlattenElement(childPrefix, prop.Value, dict); - } - break; - - case JsonValueKind.String: - dict[prefix] = element.GetString() ?? ""; - break; - - case JsonValueKind.Number: - case JsonValueKind.True: - case JsonValueKind.False: - dict[prefix] = element.ToString(); - break; - } - } - - private void OnPropertyChanged([CallerMemberName] string? propertyName = null) - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } -} diff --git a/src/ClawdDotNet.Desktop/Services/LocalizeExtension.cs b/src/ClawdDotNet.Desktop/Services/LocalizeExtension.cs deleted file mode 100644 index 2e89a57..0000000 --- a/src/ClawdDotNet.Desktop/Services/LocalizeExtension.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Avalonia.Data; -using Avalonia.Markup.Xaml; - -namespace ClawdDotNet.Desktop.Services; - -/// -/// Markup extension for Avalonia XAML: -/// Usage: Text="{services:Localize nav.chat}" -/// Updates automatically when language changes. -/// -public sealed class LocalizeExtension : MarkupExtension -{ - public string Key { get; set; } = ""; - - public LocalizeExtension() { } - - public LocalizeExtension(string key) - { - Key = key; - } - - public override object ProvideValue(IServiceProvider serviceProvider) - { - return new Binding($"[{Key}]") - { - Source = LocalizationManager.Instance, - Mode = BindingMode.OneWay - }; - } -} diff --git a/src/ClawdDotNet.Desktop/Services/ThemeManager.cs b/src/ClawdDotNet.Desktop/Services/ThemeManager.cs deleted file mode 100644 index 9ed475b..0000000 --- a/src/ClawdDotNet.Desktop/Services/ThemeManager.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Avalonia; -using Avalonia.Styling; - -namespace ClawdDotNet.Desktop.Services; - -/// -/// Hell/Dunkel umschalten — an genau einer Stelle. -/// -/// Die Farbwerte selbst stehen in Styles/Theme.axaml als -/// ThemeDictionaries. Hier wird nur umgelegt, welches der beiden Wörterbücher gilt; -/// jede Bindung mit DynamicResource zieht dann von allein nach. Deshalb gibt es -/// hier auch keine Liste von Steuerelementen, die nachgefärbt werden müssten — die wäre -/// beim nächsten neuen Bereich schon wieder unvollständig. -/// -public static class ThemeManager -{ - /// Name in den Einstellungen, wenn dunkel gewählt ist. - public const string DarkName = "Dark"; - - /// Übersetzt den gespeicherten Namen; alles außer „Dark" gilt als hell. - public static bool IsDarkName(string? name) - => string.Equals(name, DarkName, StringComparison.OrdinalIgnoreCase); - - public static string ToName(bool isDark) => isDark ? DarkName : "Light"; - - /// - /// Legt die Variante an der Anwendung um. Ohne laufende Anwendung — etwa im - /// Entwurfsmodus des Editors — passiert nichts. - /// - public static void Apply(bool isDark) - { - if (Application.Current is not { } app) return; - app.RequestedThemeVariant = isDark ? ThemeVariant.Dark : ThemeVariant.Light; - } -} diff --git a/src/ClawdDotNet.Desktop/Styles/Icons.axaml b/src/ClawdDotNet.Desktop/Styles/Icons.axaml deleted file mode 100644 index 9848df3..0000000 --- a/src/ClawdDotNet.Desktop/Styles/Icons.axaml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - M12 9c-1.5-2.5-4-3-5.5-1.5S5 11 7 12c-1 1-1.5 2-1.5 3.5S7 18 8.5 17c1-1 1.5-2 1.5-3 M12 9c1.5-2.5 4-3 5.5-1.5S19 11 17 12c1 1 1.5 2 1.5 3.5S15 18 13.5 17c-1-1-1.5-2-1.5-3 M12 9v3 - - - M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z - M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2 M13 7a4 4 0 1 1-8 0 4 4 0 0 1 8 0 M23 21v-2a4 4 0 0 0-3-3.87 M16 3.13a4 4 0 0 1 0 7.75 - M3 17l2 2 4-4 M3 7l2 2 4-4 M13 6h8 M13 12h8 M13 18h8 - M3 3v18h18 M7 15v4 M11 11v8 M15 7v12 M19 12v7 - M8 12h.01 M12 12h.01 M16 12h.01 M21 12c0 4.4-4 8-9 8-1.3 0-2.6-.2-3.7-.7L3 20l1-4.2C3.4 14.6 3 13.3 3 12c0-4.4 4-8 9-8s9 3.6 9 8Z - M3 4h18a1 1 0 0 1 1 1v3a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1z M4 9v9a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9 M10 13h4 - M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z M14 2v6h6 M9 13h6 M9 17h6 - M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0 M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.6 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9c.13-.32.19-.66.18-1a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06c.51.5 1.24.66 1.82.33H9c.32-.13.66-.19 1-.18A1.65 1.65 0 0 0 11.51 3H12a2 2 0 0 1 4 0v.09c0 .34.06.68.18 1a1.65 1.65 0 0 0 1.82.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06c-.51.5-.67 1.24-.33 1.82V9c.13.32.19.66.18 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z - M22 12a10 10 0 1 1-20 0 10 10 0 0 1 20 0 M12 16v-4 M12 8h.01 - - - M16 12a4 4 0 1 1-8 0 4 4 0 0 1 8 0 M12 2v2 M12 20v2 M4.9 4.9l1.4 1.4 M17.7 17.7l1.4 1.4 M2 12h2 M20 12h2 M4.9 19.1l1.4-1.4 M17.7 6.3l1.4-1.4 - M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z - M15 18l-6-6 6-6 - M9 18l6-6-6-6 - M6 9l6 6 6-6 - - - M12 9v4 M12 17h.01 M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z - M18 6L6 18 M6 6l12 12 - - - M12 5v14 M5 12h14 - M5 12h14 - M8 5v14l11-7z - M6 6h12v12H6z - M12 20h9 M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4Z - M3 6h18 M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2 M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6 - M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2Z - M23 4v6h-6 M1 20v-6h6 M3.51 9a9 9 0 0 1 14.85-3.36L23 10 M20.49 15a9 9 0 0 1-14.85 3.36L1 14 - M18.36 6.64a9 9 0 1 1-12.73 0 M12 2v10 - M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z M17 21v-8H7v8 M7 3v5h8 - - diff --git a/src/ClawdDotNet.Desktop/Styles/Shell.axaml b/src/ClawdDotNet.Desktop/Styles/Shell.axaml deleted file mode 100644 index 17e7013..0000000 --- a/src/ClawdDotNet.Desktop/Styles/Shell.axaml +++ /dev/null @@ -1,862 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/ClawdDotNet.Desktop/Styles/Theme.axaml b/src/ClawdDotNet.Desktop/Styles/Theme.axaml deleted file mode 100644 index a809100..0000000 --- a/src/ClawdDotNet.Desktop/Styles/Theme.axaml +++ /dev/null @@ -1,174 +0,0 @@ - - - - - - - - - - - - - - - - - #f2f2f3 - #e9e9ea - #1d1f20 - #5980a6 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #1a1c1e - #232527 - #eef0f1 - #7ea3c6 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - avares://ClawdDotNet/Assets/Fonts#Barlow Condensed - avares://ClawdDotNet/Assets/Fonts#Barlow - Cascadia Mono,Consolas,Menlo,DejaVu Sans Mono,monospace - - diff --git a/src/ClawdDotNet.Desktop/ViewLocator.cs b/src/ClawdDotNet.Desktop/ViewLocator.cs deleted file mode 100644 index 9693908..0000000 --- a/src/ClawdDotNet.Desktop/ViewLocator.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Avalonia.Controls; -using Avalonia.Controls.Templates; -using ClawdDotNet.Desktop.ViewModels; - -namespace ClawdDotNet.Desktop; - -/// -/// Findet zu einem Ansichtsmodell die passende Ansicht über die Namenskonvention -/// …ViewModels.FooViewModel → …Views.FooView. -/// -/// Das erspart es, jede Zuordnung von Hand als DataTemplate einzutragen — bei -/// den sieben Bereichen und ihren Unteransichten wären das schnell dreißig Einträge, -/// die man beim Umbenennen übersieht. -/// -/// Passt nichts, erscheint der gesuchte Typname im Fenster statt einer leeren Fläche. -/// Beim schrittweisen Umbau ist eine sichtbare Fehlstelle mehr wert als ein stiller -/// weißer Bereich. -/// -public sealed class ViewLocator : IDataTemplate -{ - public Control Build(object? data) - { - if (data is null) - return new TextBlock { Text = "(kein Inhalt)" }; - - var viewModelName = data.GetType().FullName!; - var viewName = viewModelName - .Replace(".ViewModels.", ".Views.", StringComparison.Ordinal) - .Replace("ViewModel", "View", StringComparison.Ordinal); - - var type = Type.GetType(viewName); - - if (type is null) - return new TextBlock { Text = $"Ansicht nicht gefunden: {viewName}" }; - - return (Control)Activator.CreateInstance(type)!; - } - - public bool Match(object? data) => data is ViewModelBase; -} diff --git a/src/ClawdDotNet.Desktop/ViewModels/AddAgentViewModel.cs b/src/ClawdDotNet.Desktop/ViewModels/AddAgentViewModel.cs deleted file mode 100644 index c10ef19..0000000 --- a/src/ClawdDotNet.Desktop/ViewModels/AddAgentViewModel.cs +++ /dev/null @@ -1,76 +0,0 @@ -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; - -namespace ClawdDotNet.Desktop.ViewModels; - -public sealed record AddAgentResultData( - string AgentId, - string DisplayName, - string Model, - string Description -); - -public sealed partial class AddAgentViewModel : ViewModelBase -{ - [ObservableProperty] - private string _agentId = ""; - - [ObservableProperty] - private string _displayName = ""; - - [ObservableProperty] - private string _selectedModel = "anthropic/claude-3-5-sonnet"; - - [ObservableProperty] - private string _description = ""; - - [ObservableProperty] - private string _statusMessage = ""; - - public List AvailableModels { get; } = - [ - "anthropic/claude-3-5-sonnet", - "anthropic/claude-3-opus", - "openai/gpt-4o", - "openai/gpt-4o-mini", - "google/gemini-2.5-flash", - "google/gemini-2.5-pro", - "deepseek/deepseek-r1" - ]; - - public AddAgentResultData? Result { get; private set; } - - public event Action? CloseRequested; - - [RelayCommand] - private void Confirm() - { - if (string.IsNullOrWhiteSpace(AgentId)) - { - StatusMessage = "Please enter an Agent ID."; - return; - } - - if (string.IsNullOrWhiteSpace(DisplayName)) - { - StatusMessage = "Please enter a display name."; - return; - } - - Result = new AddAgentResultData( - AgentId.Trim(), - DisplayName.Trim(), - SelectedModel, - Description.Trim() - ); - - CloseRequested?.Invoke(); - } - - [RelayCommand] - private void Cancel() - { - Result = null; - CloseRequested?.Invoke(); - } -} diff --git a/src/ClawdDotNet.Desktop/ViewModels/AddJobViewModel.cs b/src/ClawdDotNet.Desktop/ViewModels/AddJobViewModel.cs deleted file mode 100644 index f070f11..0000000 --- a/src/ClawdDotNet.Desktop/ViewModels/AddJobViewModel.cs +++ /dev/null @@ -1,111 +0,0 @@ -using ClawdDotNet.Core.Config; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; - -namespace ClawdDotNet.Desktop.ViewModels; - -public sealed record AddJobResultData( - string AgentId, - bool IsToolJob, - string ToolName, - string JobTypeId, - string CronExpression, - string TaskMessage, - bool RunOnStart -); - -public sealed partial class AddJobViewModel : ViewModelBase -{ - public List AvailableAgents { get; } - - [ObservableProperty] - private AgentConfig? _selectedAgent; - - [ObservableProperty] - private bool _isToolJob; - - [ObservableProperty] - private bool _isAgentWakeup = true; - - [ObservableProperty] - private string _selectedToolName = "FileRW"; - - [ObservableProperty] - private string _jobTypeId = "PollJob"; - - [ObservableProperty] - private string _cronExpression = "0 * * * *"; - - [ObservableProperty] - private string _taskMessage = "Execute your assigned tasks."; - - [ObservableProperty] - private bool _runOnStart; - - [ObservableProperty] - private string _statusMessage = ""; - - public List AvailableTools { get; } = - [ - "FileRW", "Telegram", "Mail", "Database", "FTP", - "DirectAPI", "WebFetch", "WebMonitor", "AgentComm", - "SocialMediaManager", "AgentSpawn", "AgentEditor", "Memory", "Taskboard" - ]; - - public AddJobResultData? Result { get; private set; } - - public event Action? CloseRequested; - - public AddJobViewModel() : this([]) { } - - public AddJobViewModel(List agents) - { - AvailableAgents = agents; - SelectedAgent = AvailableAgents.FirstOrDefault(); - } - - partial void OnIsToolJobChanged(bool value) - { - IsAgentWakeup = !value; - } - - partial void OnIsAgentWakeupChanged(bool value) - { - IsToolJob = !value; - } - - [RelayCommand] - private void Confirm() - { - if (SelectedAgent is null) - { - StatusMessage = "Please select an agent."; - return; - } - - if (string.IsNullOrWhiteSpace(CronExpression)) - { - StatusMessage = "Please enter a cron expression."; - return; - } - - Result = new AddJobResultData( - SelectedAgent.AgentId, - IsToolJob, - SelectedToolName, - JobTypeId, - CronExpression.Trim(), - TaskMessage.Trim(), - RunOnStart - ); - - CloseRequested?.Invoke(); - } - - [RelayCommand] - private void Cancel() - { - Result = null; - CloseRequested?.Invoke(); - } -} diff --git a/src/ClawdDotNet.Desktop/ViewModels/AddServiceViewModel.cs b/src/ClawdDotNet.Desktop/ViewModels/AddServiceViewModel.cs deleted file mode 100644 index 6b2f8fe..0000000 --- a/src/ClawdDotNet.Desktop/ViewModels/AddServiceViewModel.cs +++ /dev/null @@ -1,67 +0,0 @@ -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; - -namespace ClawdDotNet.Desktop.ViewModels; - -public sealed record AddServiceResultData( - string ServiceName, - string ServiceType, - int ServicePort, - string ServiceDescription -); - -public sealed partial class AddServiceViewModel : ViewModelBase -{ - [ObservableProperty] - private string _serviceName = ""; - - [ObservableProperty] - private string _serviceType = "HTTP"; - - [ObservableProperty] - private int _servicePort = 8080; - - [ObservableProperty] - private string _serviceDescription = ""; - - [ObservableProperty] - private string _statusMessage = ""; - - public List AvailableServiceTypes { get; } = ["HTTP", "TCP", "gRPC", "WebSocket", "Custom"]; - - public AddServiceResultData? Result { get; private set; } - - public event Action? CloseRequested; - - [RelayCommand] - private void Confirm() - { - if (string.IsNullOrWhiteSpace(ServiceName)) - { - StatusMessage = "Please enter a service name."; - return; - } - - if (ServicePort <= 0 || ServicePort > 65535) - { - StatusMessage = "Please enter a valid port between 1 and 65535."; - return; - } - - Result = new AddServiceResultData( - ServiceName.Trim(), - ServiceType, - ServicePort, - ServiceDescription.Trim() - ); - - CloseRequested?.Invoke(); - } - - [RelayCommand] - private void Cancel() - { - Result = null; - CloseRequested?.Invoke(); - } -} diff --git a/src/ClawdDotNet.Desktop/ViewModels/AgentChatsPageViewModel.cs b/src/ClawdDotNet.Desktop/ViewModels/AgentChatsPageViewModel.cs deleted file mode 100644 index 35b319a..0000000 --- a/src/ClawdDotNet.Desktop/ViewModels/AgentChatsPageViewModel.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System.Collections.ObjectModel; -using ClawdDotNet.App; -using CommunityToolkit.Mvvm.ComponentModel; - -namespace ClawdDotNet.Desktop.ViewModels; - -/// Eine Nachricht zwischen zwei Agenten. -public sealed class AgentMessageItem -{ - public required string SenderName { get; init; } - public required string Text { get; init; } - public required DateTime Time { get; init; } - - /// Links steht Agent A, rechts Agent B — wie im Chat mit dem Benutzer. - public required bool IsFromAgentA { get; init; } -} - -/// Ein Agent in den beiden Auswahlfeldern. -public sealed record AgentChoice(string AgentId, string DisplayName) -{ - public override string ToString() => DisplayName; -} - -/// -/// Verlauf der Nachrichten zwischen zwei Agenten. -/// -/// Ohne Datenbestand. Agenten können sich heute schon Nachrichten -/// schicken — AgentEngine.SendMessageAsync stellt zu, aber nichts schreibt den -/// Wortlaut mit. Der Speicher AgentMessages aus -/// docs/Agentenkommunikation-Konzept.md ist noch nicht gebaut. -/// -/// Die Seite steht trotzdem vollständig da: Auswahl, Filterung und Darstellung sind -/// fertig, und wenn der Speicher kommt, ist hier genau eine Abfrage zu ergänzen — -/// . Bis dahin erklärt die Seite ihren Leerzustand, statt als -/// leerer Kasten dazustehen. -/// -public sealed partial class AgentChatsPageViewModel : PageViewModel -{ - public ObservableCollection Agents { get; } = []; - public ObservableCollection Messages { get; } = []; - - [ObservableProperty] - private AgentChoice? _agentA; - - [ObservableProperty] - private AgentChoice? _agentB; - - [ObservableProperty] - private bool _isEmpty = true; - - [ObservableProperty] - private string _emptyText = ""; - - public AgentChatsPageViewModel() : this(null) { } - - public AgentChatsPageViewModel(AppHost? host) : base("nav.agentChats") - { - if (host is null) - { - Agents.Add(new AgentChoice("dev-assistant", "Dev Assistant")); - Agents.Add(new AgentChoice("social-media", "Social Media Manager")); - } - else - { - foreach (var agent in host.Instance.Agents) - Agents.Add(new AgentChoice(agent.AgentId, agent.DisplayName)); - } - - AgentA = Agents.FirstOrDefault(); - AgentB = Agents.Skip(1).FirstOrDefault() ?? AgentA; - - LoadMessages(); - } - - partial void OnAgentAChanged(AgentChoice? value) => LoadMessages(); - partial void OnAgentBChanged(AgentChoice? value) => LoadMessages(); - - /// - /// Hier kommt die Abfrage hin, sobald der AgentMessages-Speicher steht: alle - /// Nachrichten zwischen und in beiden - /// Richtungen, nach Zeit sortiert. - /// - private void LoadMessages() - { - Messages.Clear(); - - EmptyText = Agents.Count < 2 - ? LocalizationManager.Instance["desktop.agentChats.needTwo"] - : LocalizationManager.Instance["desktop.agentChats.empty"]; - - IsEmpty = Messages.Count == 0; - } -} diff --git a/src/ClawdDotNet.Desktop/ViewModels/AgentsPageViewModel.cs b/src/ClawdDotNet.Desktop/ViewModels/AgentsPageViewModel.cs deleted file mode 100644 index ebbde54..0000000 --- a/src/ClawdDotNet.Desktop/ViewModels/AgentsPageViewModel.cs +++ /dev/null @@ -1,531 +0,0 @@ -using ClawdDotNet.Core.Tasks; -using System.Collections.ObjectModel; -using Avalonia.Threading; -using ClawdDotNet.App; -using ClawdDotNet.App.Services; -using ClawdDotNet.Core.Config; -using ClawdDotNet.Core.Storage; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; -using Microsoft.Extensions.Logging; - -namespace ClawdDotNet.Desktop.ViewModels; - -public sealed partial class ToolItemViewModel : ViewModelBase -{ - public string Name { get; } - - /// - /// Kurzbeschreibung aus der Werkzeug-Registrierung. Leer, wenn das Werkzeug in dieser - /// Instanz gar nicht geladen ist — die Liste der bekannten Namen ist länger als die - /// der tatsächlich vorhandenen Werkzeuge. - /// - public string Description { get; } - - [ObservableProperty] - private bool _isEnabled; - - public ToolItemViewModel(string name, bool isEnabled, string description = "") - { - Name = name; - Description = description; - _isEnabled = isEnabled; - } -} - -public sealed partial class AgentItemViewModel : ViewModelBase -{ - public AgentConfig Config { get; } - - public string AgentId => Config.AgentId; - - [ObservableProperty] - private string _displayName; - - [ObservableProperty] - private string _model; - - [ObservableProperty] - private string _systemPrompt; - - [ObservableProperty] - private string _identity; - - [ObservableProperty] - private string _soul; - - [ObservableProperty] - private string _description; - - [ObservableProperty] - private string _promptCaching; - - [ObservableProperty] - private int _maxToolResultChars; - - [ObservableProperty] - private int _maxSteps; - - [ObservableProperty] - private int _maxContextTokens; - - [ObservableProperty] - private int _timeoutSeconds; - - [ObservableProperty] - private decimal _dailyCostUsd; - - [ObservableProperty] - private long _dailyTokens; - - /// #716: What happens to a recurring task's run when the budget is exhausted. - [ObservableProperty] - private string _whenExhausted = "expire"; - - /// The values understands. - public IReadOnlyList WhenExhaustedOptions { get; } = ["expire", "catchUpOnce"]; - - public ObservableCollection AvailableTools { get; } = []; - - /// - /// Die Namensliste steht in der Anwendungsschicht — die Weboberfläche braucht - /// dieselbe, und zwei gepflegte Listen wären eine zu viel. - /// - public static IReadOnlyList KnownTools => AgentAdministration.KnownTools; - - public AgentItemViewModel(AgentConfig config, IReadOnlyDictionary? descriptions = null) - { - Config = config; - _displayName = config.DisplayName; - _model = config.Model; - _systemPrompt = config.SystemPrompt; - _identity = config.Identity; - _soul = config.Soul; - _description = config.Description; - _promptCaching = config.PromptCaching; - _maxToolResultChars = config.MaxToolResultChars; - _maxSteps = config.LoopGuard.MaxSteps; - _maxContextTokens = config.LoopGuard.MaxContextTokens; - _timeoutSeconds = config.LoopGuard.TimeoutSeconds; - _dailyCostUsd = config.Budget.DailyCostUsd; - _dailyTokens = config.Budget.DailyTokens; - _whenExhausted = config.Budget.MissPolicy == BudgetMissPolicy.CatchUpOnce ? "catchUpOnce" : "expire"; - - foreach (var tool in KnownTools) - { - var isEnabled = config.Tools.ContainsKey(tool); - var description = descriptions?.GetValueOrDefault(tool) ?? ""; - - var item = new ToolItemViewModel(tool, isEnabled, description); - item.PropertyChanged += (_, e) => - { - if (e.PropertyName == nameof(ToolItemViewModel.IsEnabled)) - { - if (item.IsEnabled && !Config.Tools.ContainsKey(tool)) - Config.Tools[tool] = new Dictionary(); - else if (!item.IsEnabled) - Config.Tools.Remove(tool); - } - }; - AvailableTools.Add(item); - } - } - - public void ApplyChanges() - { - Config.DisplayName = DisplayName; - Config.Model = Model; - Config.SystemPrompt = SystemPrompt; - Config.Identity = Identity; - Config.Soul = Soul; - Config.Description = Description; - Config.PromptCaching = PromptCaching; - Config.MaxToolResultChars = MaxToolResultChars; - Config.LoopGuard.MaxSteps = MaxSteps; - Config.LoopGuard.MaxContextTokens = MaxContextTokens; - Config.LoopGuard.TimeoutSeconds = TimeoutSeconds; - Config.Budget.DailyCostUsd = DailyCostUsd; - Config.Budget.DailyTokens = DailyTokens; - Config.Budget.WhenExhausted = WhenExhausted; - } -} - -/// Welches Feld der Texteditor gerade bearbeitet. -public enum AgentTextField -{ - Identity, - Soul -} - -/// -/// Ansichtsmodell für die Agenten-Verwaltungsseite. -/// -/// Der Entwurf ordnet die Seite wieder wie die WinForms-Vorlage in vier Felder an: -/// oben Agentenliste und Agenteneinstellungen, unten Werkzeugliste und -/// Werkzeugeinstellungen. Für dieses Modell heißt das vor allem: Die Werkzeugeinstellungen -/// sind kein eigenes Fenster mehr, sondern hängen als an der -/// Auswahl in der Werkzeugliste. -/// -public sealed partial class AgentsPageViewModel : PageViewModel -{ - private readonly AppHost? _host; - private readonly ILogger? _logger; - - public ObservableCollection Agents { get; } = []; - - [ObservableProperty] - private AgentItemViewModel? _selectedAgent; - - /// - /// Das ausgewählte Werkzeug des ausgewählten Agenten. Steuert, welche Felder unten - /// rechts stehen. - /// - [ObservableProperty] - private ToolItemViewModel? _selectedTool; - - /// - /// Die Felder zum ausgewählten Werkzeug. Wird bei jedem Wechsel neu gebaut — das - /// Ansichtsmodell trägt die Werte von einem guten Dutzend Werkzeuge, und eines davon - /// mit den Werten eines anderen weiterzuverwenden ginge irgendwann schief. - /// - [ObservableProperty] - private ToolSettingsViewModel? _toolSettings; - - [ObservableProperty] - private string _statusText = "Bereit"; - - [ObservableProperty] - private bool _isRunning; - - public List KnownModels { get; } = - [ - "anthropic/claude-3-5-sonnet", - "anthropic/claude-3-opus", - "openai/gpt-4o", - "openai/gpt-4o-mini", - "google/gemini-2.5-flash", - "google/gemini-2.5-pro", - "deepseek/deepseek-r1" - ]; - - public List CachingOptions { get; } = ["auto", "on", "off"]; - - public event Func>? RequestAddAgentDialog; - - /// - /// Öffnet den Editor für Identity bzw. Soul. Gibt der Aufrufer einen Text zurück, - /// wurde gespeichert; null heißt Abbruch. - /// - public event Func>? RequestTextEditorDialog; - - public AgentsPageViewModel() : this(null) { } - - public AgentsPageViewModel(AppHost? host) : base("nav.agents") - { - _host = host; - - if (host is not null) - { - _logger = host.LoggerFactory.CreateLogger("ClawdDotNet.Desktop.Agents"); - ReloadAgents(); - - // Seit es eine zweite Oberflaeche gibt, ist diese Liste nicht mehr die - // einzige Quelle von Aenderungen: Ein im Browser angelegter Agent stuende - // sonst in der Datei und nicht im Fenster. Das Ereignis kommt auf dem Faden - // des Verursachers — deshalb ueber den Dispatcher. - // - // Kein Abmelden: Diese Seite lebt so lange wie die Anwendung. - host.InstanceChanged += change => - { - if (change.Kind == InstanceChangeKind.Agents) - Dispatcher.UIThread.Post(ReloadAgents); - }; - } - else - { - StatusText = LocalizationManager.Instance["desktop.status.design"]; - } - - LocalizationManager.Instance.LanguageChanged += () => OnPropertyChanged(nameof(AllowedToolsHeader)); - } - - /// - /// Beschreibungen der tatsächlich geladenen Werkzeuge. Die Namensliste in - /// ist fest verdrahtet und kennt auch - /// Werkzeuge, die in dieser Instanz nicht registriert sind — für die bleibt die - /// Beschreibung eben leer. - /// - private IReadOnlyDictionary ToolDescriptions() - => _host?.AgentAdmin.ToolDescriptions() ?? new Dictionary(); - - /// - /// Baut die Liste neu auf und behaelt die Auswahl, sofern es sie noch gibt. - /// - /// Die Auswahl zu behalten ist kein Feinschliff: Der Aufbau laeuft jetzt auch, - /// wenn die Weboberflaeche etwas geaendert hat. Waere die Auswahl danach jedesmal - /// weg, spraenge dem Benutzer der Cursor aus der Zeile, waehrend er arbeitet. - /// - [RelayCommand] - private void ReloadAgents() - { - if (_host is null) - { - Agents.Clear(); - return; - } - - var previous = SelectedAgent?.AgentId; - - Agents.Clear(); - - var descriptions = ToolDescriptions(); - - foreach (var agent in _host.Instance.Agents) - Agents.Add(new AgentItemViewModel(agent, descriptions)); - - SelectedAgent = Agents.FirstOrDefault(a => a.AgentId == previous) ?? Agents.FirstOrDefault(); - } - - public string AllowedToolsHeader => SelectedAgent is not null - ? LocalizationManager.Instance.Get("desktop.agents.allowedToolsFor", SelectedAgent.DisplayName) - : ""; - - partial void OnSelectedAgentChanged(AgentItemViewModel? value) - { - // Die Werkzeugliste unten gehört zum gewählten Agenten — bei einem Wechsel darf - // dort nicht die Auswahl des vorigen stehen bleiben. - SelectedTool = value?.AvailableTools.FirstOrDefault(); - OnPropertyChanged(nameof(AllowedToolsHeader)); - } - - partial void OnSelectedToolChanged(ToolItemViewModel? value) - { - if (SelectedAgent is null || value is null) - { - ToolSettings = null; - return; - } - - // Auch für ein noch nicht zugelassenes Werkzeug sollen die Felder sichtbar sein — - // sonst müsste man erst ankreuzen, um zu sehen, was einzustellen wäre. - if (!SelectedAgent.Config.Tools.TryGetValue(value.Name, out var config) || config is null) - config = new Dictionary(); - - ToolSettings = new ToolSettingsViewModel(value.Name, config); - } - - [RelayCommand] - private async Task AddAgentAsync() - { - if (_host is null || RequestAddAgentDialog is null) return; - - var vm = new AddAgentViewModel(); - var result = await RequestAddAgentDialog(vm); - if (result is null) return; - - // Erst die offenen Änderungen der Liste sichern, dann anlegen: Der Aufruf - // schreibt die Instanzdatei, und was hier noch nicht übernommen war, ginge sonst - // verloren. - ApplyPendingEdits(); - - var outcome = _host.AgentAdmin.Add( - new NewAgent(result.AgentId, result.DisplayName, result.Model, result.Description)); - - StatusText = outcome.Message; - if (!outcome.Ok) return; - - if (_host.AgentAdmin.Find(result.AgentId) is not { } newConfig) return; - - var item = new AgentItemViewModel(newConfig, ToolDescriptions()); - Agents.Add(item); - SelectedAgent = item; - } - - [RelayCommand] - private void RemoveAgent() - { - if (_host is null || SelectedAgent is null) return; - - var removed = SelectedAgent; - ApplyPendingEdits(); - - var outcome = _host.AgentAdmin.Remove(removed.AgentId); - StatusText = outcome.Message; - if (!outcome.Ok) return; - - Agents.Remove(removed); - SelectedAgent = Agents.FirstOrDefault(); - } - - /// - /// Weckt den gewählten Agenten von Hand — im Entwurf die Schaltfläche „Jetzt ausf.". - /// Nimmt dieselbe Nachricht wie der geplante Lauf, damit der Handlauf zeigt, was der - /// geplante täte. - /// - [RelayCommand] - private async Task RunAgentNowAsync() - { - if (_host is null || SelectedAgent is null) return; - - if (_host.Engine is null) - { - StatusText = LocalizationManager.Instance["desktop.chat.noApiKey"]; - return; - } - - var config = SelectedAgent.Config; - - IsRunning = true; - StatusText = $"Running '{config.DisplayName}'…"; - - try - { - var outcome = await _host.Runs.RunAgentAsync( - config.AgentId, config.Scheduler?.TaskMessage, CancellationToken.None); - - StatusText = outcome.Message; - - if (!outcome.Ok) - _logger?.LogWarning("Agent execution failed: {Reason}", outcome.Message); - } - finally - { - IsRunning = false; - } - } - - [RelayCommand] - private Task EditIdentityAsync() => EditTextFieldAsync(AgentTextField.Identity); - - [RelayCommand] - private Task EditSoulAsync() => EditTextFieldAsync(AgentTextField.Soul); - - /// - /// Identity und Soul sind lange Texte. Der Entwurf gibt ihnen ein eigenes kleines - /// Fenster statt eines Feldes in der Spalte — in einem 60 Pixel hohen Kasten lässt - /// sich eine Rollenbeschreibung nicht schreiben. - /// - private async Task EditTextFieldAsync(AgentTextField field) - { - if (SelectedAgent is null || RequestTextEditorDialog is null) return; - - var isIdentity = field == AgentTextField.Identity; - var title = isIdentity - ? $"Edit Identity — {SelectedAgent.DisplayName}" - : $"Edit Soul — {SelectedAgent.DisplayName}"; - - var current = isIdentity ? SelectedAgent.Identity : SelectedAgent.Soul; - - var edited = await RequestTextEditorDialog(title, current); - if (edited is null) return; - - if (isIdentity) SelectedAgent.Identity = edited; - else SelectedAgent.Soul = edited; - - SaveAgents(); - } - - /// Öffnet den Arbeitsordner des gewählten Agenten. - [RelayCommand] - private void OpenAgentFolder() - { - if (_host is null || SelectedAgent is null) return; - - var path = _host.Directories.GetAgentPath(_host.InstancePath, SelectedAgent.DisplayName); - - if (!Directory.Exists(path)) - { - StatusText = $"Folder not found: {path}"; - return; - } - - SystemShell.OpenFolder(path); - } - - /// - /// Übernimmt die Felder des gewählten Werkzeugs in die Agentenkonfiguration. - /// - /// Das Ankreuzfeld in der Liste und diese Schaltfläche sind zwei verschiedene - /// Dinge: Ersteres lässt das Werkzeug zu, letztere schreibt seine Einstellungen. Wer - /// nur ankreuzt, bekommt ein Werkzeug mit Vorgabewerten — das ist gewollt. - /// - [RelayCommand] - private void SaveToolSettings() - { - if (_host is null || SelectedAgent is null || SelectedTool is null || ToolSettings is null) return; - - ToolSettings.ConfirmCommand.Execute(null); - - if (ToolSettings.Result is not { } config) return; - - // Einstellungen zu schreiben heißt, das Werkzeug zu wollen — das Ankreuzfeld - // zieht nach, damit Liste und Konfiguration nicht auseinanderlaufen. - SelectedTool.IsEnabled = true; - - ApplyPendingEdits(); - StatusText = _host.AgentAdmin - .SetToolSettings(SelectedAgent.AgentId, SelectedTool.Name, config).Message; - } - - [RelayCommand] - private void SaveAgents() - { - if (_host is null) return; - - ApplyPendingEdits(); - _host.AgentAdmin.Save(); - - _logger?.LogInformation("Agents configuration saved."); - StatusText = LocalizationManager.Instance["desktop.agents.saved"]; - } - - /// - /// Überträgt, was in den Feldern der Seite steht, in die Konfigurationsobjekte. - /// - /// Die Ansichtsmodelle halten eigene Eigenschaften und schreiben sie erst bei - /// ApplyChanges zurück. Jeder Aufruf, der gleich die Instanzdatei schreibt, - /// muss vorher hier durch — sonst verschwindet eine gerade getippte Änderung, weil - /// jemand nebenbei einen Agenten angelegt hat. - /// - private void ApplyPendingEdits() - { - foreach (var agentVm in Agents) - agentVm.ApplyChanges(); - } - - // ─── Teilerstellungen ─── - // - // Die drei Teiler der Seite sollen den Neustart ueberleben. Gespeichert wird ein - // Verhaeltnis, kein Pixelwert: Sonst sitzt der Teiler nach einem Wechsel auf einen - // anderen Bildschirm an einer voellig anderen Stelle. - - public double SplitVertical => Clamp(_host?.Settings.AppSettings.AgentsSplitVertical ?? 0.55); - public double SplitTopList => Clamp(_host?.Settings.AppSettings.AgentsSplitTopList ?? 0.44); - public double SplitBottomList => Clamp(_host?.Settings.AppSettings.AgentsSplitBottomList ?? 0.44); - - /// - /// Hält den Teiler in einem Bereich, in dem beide Seiten noch bedienbar sind. Ein - /// gespeicherter Wert von 0.02 hätte eine Spalte auf einen Strich zusammengezogen und - /// wäre ohne Zurücksetzen nicht mehr aufzuziehen gewesen. - /// - private static double Clamp(double ratio) - => double.IsFinite(ratio) ? Math.Clamp(ratio, 0.2, 0.8) : 0.5; - - public void SaveSplits(double vertical, double topList, double bottomList) - { - if (_host is null) return; - - try - { - var settings = _host.Settings.AppSettings; - settings.AgentsSplitVertical = Clamp(vertical); - settings.AgentsSplitTopList = Clamp(topList); - settings.AgentsSplitBottomList = Clamp(bottomList); - _host.Settings.Save(); - } - catch (Exception) - { - // Eine Teilerstellung ist es nicht wert, die Bedienung zu unterbrechen. - } - } -} diff --git a/src/ClawdDotNet.Desktop/ViewModels/BackupPageViewModel.cs b/src/ClawdDotNet.Desktop/ViewModels/BackupPageViewModel.cs deleted file mode 100644 index 92b362a..0000000 --- a/src/ClawdDotNet.Desktop/ViewModels/BackupPageViewModel.cs +++ /dev/null @@ -1,415 +0,0 @@ -using System.Collections.ObjectModel; -using Avalonia.Threading; -using ClawdDotNet.App; -using ClawdDotNet.App.Services; -using ClawdDotNet.Core.Backup; -using ClawdDotNet.Core.Config; -using ClawdDotNet.Core.Storage; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; -using Microsoft.Extensions.Logging; - -namespace ClawdDotNet.Desktop.ViewModels; - -public sealed record BackupItemViewModel( - string FileName, - DateTime LastWriteTime, - string InstanceName, - long SizeBytes, - string SizeFormatted, - bool HasSecrets, - string SecretsInfo, - string FullPath, - bool IsReadable -); - -/// -/// Ansichtsmodell für die Sicherungs- und Wiederherstellungsseite. -/// -public sealed partial class BackupPageViewModel : PageViewModel -{ - private readonly BackupService _service = new(); - private readonly AppHost? _host; - - /// - /// Schalter, Uhrzeit, Zielordner und Aufbewahrung stehen seit #528 (Stufe 1) hier - /// und nicht mehr in den Anwendungseinstellungen. Dort galten sie fuer jede Instanz: - /// Wer die taegliche Sicherung fuer eine einschaltete, schaltete sie fuer alle ein. - /// - private readonly InstanceConfig? _instance; - - private readonly ILogger? _logger; - private readonly string _instanceDir; - private readonly string _instanceName; - private bool _loading; - - [ObservableProperty] - private string _targetFolder = ""; - - [ObservableProperty] - private bool _secretsExclude = true; - - [ObservableProperty] - private bool _secretsPassphrase; - - [ObservableProperty] - private string _passphrase = ""; - - [ObservableProperty] - private string _passphraseRepeat = ""; - - [ObservableProperty] - private bool _includeLogs; - - [ObservableProperty] - private bool _includeChatHistory = true; - - [ObservableProperty] - private bool _autoBackupEnabled; - - [ObservableProperty] - private string _autoBackupTime = "03:00"; - - [ObservableProperty] - private int _keepCount = 10; - - [ObservableProperty] - private string _statusText = LocalizationManager.Instance["common.ready"]; - - [ObservableProperty] - private bool _isBusy; - - [ObservableProperty] - private BackupItemViewModel? _selectedBackup; - - public ObservableCollection Backups { get; } = []; - - public event Func>? RequestRestoreDialog; - - public BackupPageViewModel() : this(null) { } - - public BackupPageViewModel(AppHost? host) : base("nav.backup") - { - _host = host; - - if (host is not null) - { - _instanceDir = host.InstancePath; - _instanceName = host.Instance.InstanceName; - _instance = host.Instance; - _logger = host.LoggerFactory.CreateLogger("ClawdDotNet.Desktop.Backup"); - - LoadSettings(); - RefreshBackupList(); - } - else - { - _instanceDir = ""; - _instanceName = "Entwurf"; - TargetFolder = @"C:\ClawdDotNet\Backups"; - } - } - - partial void OnAutoBackupEnabledChanged(bool value) => SaveSettings(); - partial void OnAutoBackupTimeChanged(string value) => SaveSettings(); - partial void OnKeepCountChanged(int value) => SaveSettings(); - - private void LoadSettings() - { - if (_host is null || _instance is null) return; - - _loading = true; - try - { - // Aufgeloest und nicht roh angezeigt: In der Datei steht in aller Regel - // nichts, und ein leeres Feld beantwortet die Frage nicht, wohin gesichert - // wird. - TargetFolder = AppHost.ResolveBackupDirectory(_instance, _instanceDir); - AutoBackupEnabled = _instance.AutoBackupEnabled; - KeepCount = Math.Clamp(_instance.BackupKeepCount, 0, 999); - - AutoBackupTime = TimeSpan.TryParse(_instance.AutoBackupTime, out var time) - ? time.ToString(@"hh\:mm") - : "03:00"; - } - finally - { - _loading = false; - } - } - - public void SaveSettings() - { - if (_loading || _host is null || _instance is null) return; - - var folder = TargetFolder.Trim(); - - // Der Vorgabeort bleibt als Leereintrag stehen. Sonst schriebe die Ansicht den - // aufgeloesten Pfad fest, und eine umgezogene Instanz sicherte weiter dorthin, - // wo sie einmal lag. - var vorgabe = AppHost.ResolveBackupDirectory(new InstanceConfig(), _instanceDir); - - _instance.BackupDirectory = - string.Equals(folder, vorgabe, PathBoundary.Comparison) ? "" : folder; - - _instance.AutoBackupEnabled = AutoBackupEnabled; - _instance.AutoBackupTime = AutoBackupTime.Trim(); - _instance.BackupKeepCount = KeepCount; - - _host.SaveInstance(new InstanceChange(InstanceChangeKind.Settings)); - } - - [RelayCommand] - private void RefreshBackupList() - { - Backups.Clear(); - var folder = TargetFolder.Trim(); - - if (string.IsNullOrWhiteSpace(folder) || !Directory.Exists(folder)) - return; - - Task.Run(async () => - { - var files = new DirectoryInfo(folder) - .GetFiles("*.zip") - .OrderByDescending(f => f.LastWriteTime) - .ToList(); - - var list = new List(); - - foreach (var file in files) - { - try - { - var manifest = await _service.InspectAsync(file.FullName); - var secretsInfo = manifest.HasSecrets - ? $"ja ({manifest.SecretCount}, Passphrase)" - : "nein"; - - list.Add(new BackupItemViewModel( - file.Name, file.LastWriteTime, manifest.InstanceName, - file.Length, FormatSize(file.Length), manifest.HasSecrets, secretsInfo, - file.FullName, true)); - } - catch - { - list.Add(new BackupItemViewModel( - file.Name, file.LastWriteTime, "—", - file.Length, FormatSize(file.Length), false, "unlesbar", - file.FullName, false)); - } - } - - await Dispatcher.UIThread.InvokeAsync(() => - { - Backups.Clear(); - foreach (var item in list) - Backups.Add(item); - }); - }); - } - - [RelayCommand] - private async Task CreateBackupAsync() - { - if (string.IsNullOrWhiteSpace(_instanceDir)) - { - StatusText = "Keine gültige Instanz geladen."; - return; - } - - var folder = TargetFolder.Trim(); - if (string.IsNullOrWhiteSpace(folder)) - { - StatusText = "Bitte einen Zielordner angeben."; - return; - } - - BackupOptions options; - if (SecretsPassphrase) - { - if (string.IsNullOrEmpty(Passphrase)) - { - StatusText = "Bitte eine Passphrase eingeben."; - return; - } - - if (Passphrase != PassphraseRepeat) - { - StatusText = "Die Passphrasen stimmen nicht überein."; - return; - } - - options = new BackupOptions - { - Secrets = SecretMode.Passphrase, - Passphrase = Passphrase, - IncludeLogs = IncludeLogs, - IncludeChatHistory = IncludeChatHistory - }; - } - else - { - options = new BackupOptions - { - Secrets = SecretMode.Exclude, - IncludeLogs = IncludeLogs, - IncludeChatHistory = IncludeChatHistory - }; - } - - Directory.CreateDirectory(folder); - var fileName = BuildFileName(); - var zipPath = Path.Combine(folder, fileName); - - IsBusy = true; - StatusText = "Sicherung läuft…"; - - try - { - var result = await Task.Run(() => _service.CreateAsync(_instanceDir, zipPath, options)); - - StatusText = $"Fertig: {Path.GetFileName(result.ZipPath)} ({FormatSize(result.SizeBytes)})"; - _logger?.LogInformation("Sicherung erstellt: {Path} ({Size} Bytes)", result.ZipPath, result.SizeBytes); - - Passphrase = ""; - PassphraseRepeat = ""; - - ApplyRotation(folder); - RefreshBackupList(); - } - catch (Exception ex) - { - StatusText = $"Fehler: {ex.Message}"; - _logger?.LogError(ex, "Sicherung fehlgeschlagen"); - } - finally - { - IsBusy = false; - } - } - - [RelayCommand] - private void ShowSelectedInFolder() - { - if (SelectedBackup is null) return; - SystemShell.RevealFile(SelectedBackup.FullPath); - } - - [RelayCommand] - private void DeleteSelected() - { - if (SelectedBackup is null) return; - - try - { - File.Delete(SelectedBackup.FullPath); - RefreshBackupList(); - StatusText = $"Gelöscht: {SelectedBackup.FileName}"; - } - catch (Exception ex) - { - StatusText = $"Konnte nicht gelöscht werden: {ex.Message}"; - } - } - - [RelayCommand] - private async Task RestoreSelectedAsync() - { - if (SelectedBackup is null || RequestRestoreDialog is null) return; - - BackupManifest manifest; - try - { - manifest = await _service.InspectAsync(SelectedBackup.FullPath); - } - catch (Exception ex) - { - StatusText = $"Sicherung unlesbar: {ex.Message}"; - return; - } - - var suggestedTarget = SuggestRestoreTarget(manifest); - var vm = new RestoreBackupViewModel(manifest, suggestedTarget); - - var resultData = await RequestRestoreDialog(vm); - if (resultData is null) return; - - IsBusy = true; - StatusText = "Wiederherstellung läuft…"; - - try - { - var restoreOptions = new RestoreOptions - { - Passphrase = resultData.Passphrase, - Overwrite = resultData.Overwrite - }; - - var result = await Task.Run(() => _service.RestoreAsync( - SelectedBackup.FullPath, resultData.TargetDirectory, restoreOptions)); - - StatusText = $"{result.Written.Count} Datei(en) wiederhergestellt nach {resultData.TargetDirectory}"; - _logger?.LogInformation("Wiederherstellung: {Written} geschrieben nach {Target}", - result.Written.Count, resultData.TargetDirectory); - } - catch (Exception ex) - { - StatusText = $"Wiederherstellung fehlgeschlagen: {ex.Message}"; - _logger?.LogError(ex, "Wiederherstellung fehlgeschlagen"); - } - finally - { - IsBusy = false; - } - } - - private string BuildFileName() - { - var name = string.IsNullOrWhiteSpace(_instanceName) ? "Instanz" : _instanceName; - var safeName = string.Concat(name.Select(c => Path.GetInvalidFileNameChars().Contains(c) ? '_' : c)); - return $"backup_{safeName}_{DateTime.Now:yyyy-MM-dd_HHmm}.zip"; - } - - private string SuggestRestoreTarget(BackupManifest manifest) - { - var parent = Directory.GetParent(_instanceDir)?.FullName ?? _instanceDir; - var name = string.IsNullOrWhiteSpace(manifest.InstanceName) ? "Instanz" : manifest.InstanceName; - var safeName = string.Concat(name.Select(c => Path.GetInvalidFileNameChars().Contains(c) ? '_' : c)); - return Path.Combine(parent, $"Instance-{safeName}_wiederhergestellt_{DateTime.Now:yyyyMMdd_HHmm}"); - } - - private void ApplyRotation(string folder) - { - if (KeepCount <= 0 || !Directory.Exists(folder)) return; - - try - { - var prefix = $"backup_{_instanceName}_"; - var obsolete = new DirectoryInfo(folder) - .GetFiles("*.zip") - .Where(f => f.Name.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) - .OrderByDescending(f => f.LastWriteTime) - .Skip(KeepCount) - .ToList(); - - foreach (var file in obsolete) - { - file.Delete(); - _logger?.LogInformation("Alte Sicherung rotiert: {Name}", file.Name); - } - } - catch (Exception ex) - { - _logger?.LogWarning(ex, "Rotation der Sicherungen fehlgeschlagen"); - } - } - - private static string FormatSize(long bytes) => bytes switch - { - < 1024 => $"{bytes} B", - < 1024 * 1024 => $"{bytes / 1024.0:F1} KB", - < 1024L * 1024 * 1024 => $"{bytes / 1024.0 / 1024:F1} MB", - _ => $"{bytes / 1024.0 / 1024 / 1024:F2} GB" - }; -} diff --git a/src/ClawdDotNet.Desktop/ViewModels/ChatPageViewModel.cs b/src/ClawdDotNet.Desktop/ViewModels/ChatPageViewModel.cs deleted file mode 100644 index e9db1bb..0000000 --- a/src/ClawdDotNet.Desktop/ViewModels/ChatPageViewModel.cs +++ /dev/null @@ -1,158 +0,0 @@ -using System.Collections.ObjectModel; -using Avalonia.Threading; -using ClawdDotNet.App; -using ClawdDotNet.Core.Config; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; - -namespace ClawdDotNet.Desktop.ViewModels; - -public sealed record ChatEntryItemViewModel( - string Role, - string Sender, - string Text, - DateTime Timestamp, - bool IsUser -); - -/// -/// Ansichtsmodell für die native Chat-Seite (Avalonia UI statt WebView2). -/// -public sealed partial class ChatPageViewModel : PageViewModel -{ - private readonly AppHost? _host; - - public ObservableCollection AvailableAgents { get; } = []; - public ObservableCollection ChatEntries { get; } = []; - - [ObservableProperty] - private AgentConfig? _selectedAgent; - - [ObservableProperty] - private string _inputPrompt = ""; - - [ObservableProperty] - private bool _isSending; - - [ObservableProperty] - private string _statusText = "Ready"; - - public ChatPageViewModel() : this(null) { } - - public ChatPageViewModel(AppHost? host) : base("nav.chat") - { - _host = host; - - if (host is not null) - { - foreach (var agent in host.Instance.Agents) - AvailableAgents.Add(agent); - - SelectedAgent = AvailableAgents.FirstOrDefault(); - - if (host.Engine is not null) - { - host.Engine.OnChatEntryAdded += OnEngineChatEntryAdded; - } - } - else - { - StatusText = "Design Mode"; - } - } - - partial void OnSelectedAgentChanged(AgentConfig? value) - { - LoadChatHistory(); - } - - private void LoadChatHistory() - { - ChatEntries.Clear(); - if (_host?.Engine is null || SelectedAgent is null) return; - - var history = _host.Engine.GetChatHistory(SelectedAgent.AgentId); - foreach (var entry in history) - { - var isUser = entry.Role.Equals("user", StringComparison.OrdinalIgnoreCase); - ChatEntries.Add(new ChatEntryItemViewModel( - entry.Role, - isUser ? "You" : SelectedAgent.DisplayName, - entry.Content, - entry.Timestamp, - isUser - )); - } - - StatusText = $"Chat history for '{SelectedAgent.DisplayName}' loaded ({ChatEntries.Count} messages)."; - } - - private void OnEngineChatEntryAdded(string agentId, string role, string text, string? toolName) - { - if (SelectedAgent is null || SelectedAgent.AgentId != agentId) return; - - Dispatcher.UIThread.Post(() => - { - var isUser = role.Equals("user", StringComparison.OrdinalIgnoreCase); - var sender = isUser ? "You" : (string.IsNullOrWhiteSpace(toolName) ? SelectedAgent.DisplayName : $"Tool: {toolName}"); - - ChatEntries.Add(new ChatEntryItemViewModel( - role, sender, text, DateTime.Now, isUser - )); - }); - } - - [RelayCommand] - private async Task SendMessageAsync() - { - if (_host?.Engine is null || SelectedAgent is null) - { - StatusText = "Engine not active or no agent selected."; - return; - } - - var text = InputPrompt.Trim(); - if (string.IsNullOrWhiteSpace(text)) return; - - InputPrompt = ""; - IsSending = true; - StatusText = $"{SelectedAgent.DisplayName} is thinking…"; - - try - { - var agent = SelectedAgent; - var instanceId = _host.Instance.InstanceId; - - var result = await Task.Run(() => - _host.Engine.ChatAsync(agent, text, instanceId, CancellationToken.None)); - - StatusText = $"{agent.DisplayName} finished ({result.Status}, {result.TokensUsed:N0} tokens)."; - } - catch (Exception ex) - { - StatusText = $"Error: {ex.Message}"; - } - finally - { - IsSending = false; - } - } - - [RelayCommand] - private void Abort() - { - if (_host?.Engine is null || SelectedAgent is null) return; - _host.Engine.AbortChat(SelectedAgent.AgentId); - StatusText = "Chat abgebrochen."; - IsSending = false; - } - - [RelayCommand] - private void ClearHistory() - { - if (_host?.Engine is null || SelectedAgent is null) return; - _host.Engine.ClearChatHistory(SelectedAgent.AgentId); - ChatEntries.Clear(); - StatusText = "Verlauf geleert."; - } -} diff --git a/src/ClawdDotNet.Desktop/ViewModels/InfoPageViewModel.cs b/src/ClawdDotNet.Desktop/ViewModels/InfoPageViewModel.cs deleted file mode 100644 index e1c4aef..0000000 --- a/src/ClawdDotNet.Desktop/ViewModels/InfoPageViewModel.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System.Collections.ObjectModel; -using System.Reflection; -using ClawdDotNet.App; -using ClawdDotNet.Core.Storage; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; - -namespace ClawdDotNet.Desktop.ViewModels; - -public sealed record AssemblyInfoItem(string ShortName, int BuildNumber, string BuildDate, string Changes); - -/// -/// Ansichtsmodell für die Info-Seite (Version, Build-Informationen, Instanz-Details). -/// -public sealed partial class InfoPageViewModel : PageViewModel -{ - [ObservableProperty] - private string _appVersion = "—"; - - [ObservableProperty] - private string _buildSummary = "—"; - - [ObservableProperty] - private string _instanceName = "—"; - - [ObservableProperty] - private string _instanceId = "—"; - - [ObservableProperty] - private string _instancePath = "—"; - - [ObservableProperty] - private string _logDirectory = "—"; - - [ObservableProperty] - private string _openRouterStatus = "—"; - - public ObservableCollection Assemblies { get; } = []; - - public InfoPageViewModel() : this(null) { } - - public InfoPageViewModel(AppHost? host) : base("nav.info") - { - AppVersion = AppHost.AppVersion; - BuildSummary = AppHost.BuildSummary; - - if (host is not null) - { - InstanceName = host.Instance.InstanceName; - InstanceId = host.Instance.InstanceId; - InstancePath = host.InstancePath; - LogDirectory = host.LogDirectory; - OpenRouterStatus = host.Engine is null - ? "Disabled (no API key configured)" - : "Active (AgentEngine ready)"; - } - else - { - InstanceName = "Design Mode"; - InstanceId = "00000000-0000-0000-0000-000000000000"; - InstancePath = @"C:\ClawdDotNet\Instances\Default"; - LogDirectory = @"C:\ClawdDotNet\Logs"; - OpenRouterStatus = "Design"; - } - - LoadAssemblyBuildInfos(); - } - - /// - /// Fruehere Menueleiste, Punkt „Bearbeiten > Instanz-Ordner oeffnen". Der Entwurf - /// kennt keine Menueleiste mehr; der Befehl sitzt jetzt dort, wo auch der Pfad steht. - /// - [RelayCommand] - private void OpenInstanceFolder() - { - if (!Directory.Exists(InstancePath)) return; - SystemShell.OpenFolder(InstancePath); - } - - private void LoadAssemblyBuildInfos() - { - Assemblies.Clear(); - - foreach (var asm in AppDomain.CurrentDomain.GetAssemblies() - .Where(a => a.GetName().Name?.StartsWith("ClawdDotNet") == true) - .OrderBy(a => a.GetName().Name)) - { - var name = asm.GetName().Name!; - var shortName = name.Replace("ClawdDotNet.", "").Replace("Tools.", ""); - - var buildDate = asm.GetCustomAttributes(typeof(AssemblyMetadataAttribute), false) - .OfType() - .FirstOrDefault(a => a.Key == "BuildDate")?.Value ?? "?"; - - var buildInfoType = asm.GetType(asm.GetName().Name + ".BuildInfo"); - var buildNum = buildInfoType?.GetField("Build")?.GetValue(null) as int? ?? 0; - var changes = buildInfoType?.GetField("Changes")?.GetValue(null) as string ?? "—"; - - Assemblies.Add(new AssemblyInfoItem(shortName, buildNum, buildDate, changes)); - } - } -} diff --git a/src/ClawdDotNet.Desktop/ViewModels/InstancePickerViewModel.cs b/src/ClawdDotNet.Desktop/ViewModels/InstancePickerViewModel.cs deleted file mode 100644 index 17fc056..0000000 --- a/src/ClawdDotNet.Desktop/ViewModels/InstancePickerViewModel.cs +++ /dev/null @@ -1,190 +0,0 @@ -using System.Collections.ObjectModel; -using ClawdDotNet.App.Models; -using ClawdDotNet.App.Services; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; -using ClawdDotNet.Core.Instances; - -namespace ClawdDotNet.Desktop.ViewModels; - -/// -/// Eine Instanz in der Auswahl. -/// -/// Das Monogramm und der Punkt stammen aus dem Entwurf. Der Punkt zeigt bewusst -/// Bereitschaft und nicht „läuft": Ob eine andere Instanz gerade läuft, weiß -/// diese Anwendung nicht — jede Instanz ist ein eigener Prozess, und einen -/// instanzübergreifenden Status gibt es noch nicht. Ein grüner Punkt für „läuft" wäre -/// hier schlicht geraten. -/// -public sealed class InstanceChoiceViewModel(InstanceInfo info, bool isCurrent) -{ - public InstanceInfo Info { get; } = info; - - public string InstanceName => Info.InstanceName; - public string FolderPath => Info.FolderPath; - - /// Erste zwei Buchstaben, gross — wie im Entwurf. - public string Monogram => Info.InstanceName.Length >= 2 - ? Info.InstanceName[..2].ToUpperInvariant() - : Info.InstanceName.ToUpperInvariant(); - - public string Summary - { - get - { - var keyStatus = IsReady - ? LocalizationManager.Instance["desktop.instancePicker.apiKeyConfigured"] - : LocalizationManager.Instance["desktop.instancePicker.apiKeyMissing"]; - return string.Format( - LocalizationManager.Instance["desktop.instancePicker.agentsCount"], - Info.AgentCount, - keyStatus); - } - } - - /// Ohne API-Key kann die Instanz keine Agenten starten. - public bool IsReady => Info.ApiKeyStatus.Equals("Konfiguriert", StringComparison.OrdinalIgnoreCase) - || Info.ApiKeyStatus.Equals("Configured", StringComparison.OrdinalIgnoreCase); - - /// Die gerade laufende Instanz — traegt im Entwurf das Etikett „Aktiv". - public bool IsCurrent { get; } = isCurrent; -} - -/// -/// Auswahl der Instanz — beim Start und beim Wechseln aus der laufenden Anwendung. -/// -/// Die WinForms-Fassung mischte Datenzugriff, Spaltenformatierung und Meldungsfenster -/// in einem Formular. Hier steht nur, was geschieht; das wie es aussieht -/// liegt in der Ansicht, und Rückfragen laufen über statt über -/// einen direkten Dialogaufruf — so bleibt das Ansichtsmodell ohne Fensterbezug prüfbar. -/// -public sealed partial class InstancePickerViewModel : ViewModelBase -{ - private readonly InstanceDirectoryManager _directories; - private readonly TaskCompletionSource _completion = new(); - private readonly string? _currentInstancePath; - - [ObservableProperty] - [NotifyCanExecuteChangedFor(nameof(StartCommand))] - private InstanceChoiceViewModel? _selected; - - [ObservableProperty] - private string _newInstanceName = ""; - - /// Fehlertext für die Ansicht; leer heißt: alles in Ordnung. - [ObservableProperty] - private string _errorText = ""; - - public ObservableCollection Instances { get; } = []; - - /// Der gewählte Pfad, oder null bei Abbruch. - public Task Result => _completion.Task; - - public string InstancesDirectory => _directories.InstancesDirectory; - - /// - /// Beim Start heisst die Schaltflaeche „Starten", aus der laufenden Anwendung heraus - /// „Wechseln" — und dann steht der Hinweis dabei, dass dafuer neu gestartet wird. - /// - public bool IsSwitchMode => _currentInstancePath is not null; - - public string ConfirmLabel => IsSwitchMode - ? LocalizationManager.Instance["desktop.instancePicker.confirmSwitch"] - : LocalizationManager.Instance["desktop.instancePicker.confirmStart"]; - - /// Ueberschrift des Dialogs — nicht aus ConfirmLabel zusammengesetzt, - /// sonst stuende dort „Instanz Starten". - public string Title => IsSwitchMode - ? LocalizationManager.Instance["desktop.instancePicker.titleSwitch"] - : LocalizationManager.Instance["desktop.instancePicker.titleSelect"]; - - public string Hint => IsSwitchMode - ? LocalizationManager.Instance["desktop.instancePicker.hintSwitch"] - : LocalizationManager.Instance["desktop.instancePicker.hintSelect"]; - - /// - /// Pfad der laufenden Instanz, oder null beim Start. Steuert Beschriftung und - /// das Etikett „Aktiv" in der Liste. - /// - public InstancePickerViewModel(InstanceDirectoryManager directories, string? currentInstancePath = null) - { - _directories = directories; - _currentInstancePath = currentInstancePath; - Refresh(); - } - - [RelayCommand] - private void Refresh() - { - Instances.Clear(); - - foreach (var instance in _directories.ListInstances()) - { - var isCurrent = _currentInstancePath is not null - && string.Equals(instance.FolderPath, _currentInstancePath, - StringComparison.OrdinalIgnoreCase); - - Instances.Add(new InstanceChoiceViewModel(instance, isCurrent)); - } - - // Eine einzelne Instanz gleich vorwählen — der häufigste Fall, und ein Klick - // weniger bei jedem Start. - Selected ??= Instances.FirstOrDefault(i => i.IsCurrent) ?? Instances.FirstOrDefault(); - } - - private bool CanStart => Selected is not null; - - [RelayCommand(CanExecute = nameof(CanStart))] - private void Start() => _completion.TrySetResult(Selected!.FolderPath); - - /// Waehlt eine Zeile und bestaetigt in einem Zug — die Schaltflaeche je Zeile. - [RelayCommand] - private void Activate(InstanceChoiceViewModel? choice) - { - if (choice is null) return; - Selected = choice; - _completion.TrySetResult(choice.FolderPath); - } - - /// Abbruch — der Aufrufer beendet die Anwendung oder schliesst den Dialog. - [RelayCommand] - private void Cancel() => _completion.TrySetResult(null); - - [RelayCommand] - private void Create() - { - var name = NewInstanceName.Trim(); - - if (string.IsNullOrWhiteSpace(name)) - { - ErrorText = LocalizationManager.Instance["desktop.instancePicker.nameRequired"]; - return; - } - - try - { - _directories.CreateInstance(name); - NewInstanceName = ""; - ErrorText = ""; - Refresh(); - - // Die frisch angelegte Instanz vorwählen — wer sie erstellt, will sie starten. - Selected = Instances.FirstOrDefault(i => - string.Equals(i.InstanceName, name, StringComparison.Ordinal)); - } - catch (Exception ex) when (ex is IOException or UnauthorizedAccessException - or ArgumentException) - { - ErrorText = string.Format( - LocalizationManager.Instance["desktop.instancePicker.createFailed"], - ex.Message); - } - } - - /// - /// Wird gesetzt, wenn ein Fehler von außen kommt (etwa eine unlesbare - /// Instanzkonfiguration), damit das Fenster offen bleiben und eine andere Wahl - /// zulassen kann. - /// - public void ConfirmError(string message) => ErrorText = message; -} diff --git a/src/ClawdDotNet.Desktop/ViewModels/LicenseViewModel.cs b/src/ClawdDotNet.Desktop/ViewModels/LicenseViewModel.cs deleted file mode 100644 index 5cdfad1..0000000 --- a/src/ClawdDotNet.Desktop/ViewModels/LicenseViewModel.cs +++ /dev/null @@ -1,46 +0,0 @@ -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; - -namespace ClawdDotNet.Desktop.ViewModels; - -/// Eingabe eines Lizenzschlüssels. Siehe AvaloniaLicensePrompt. -public sealed partial class LicenseViewModel : ViewModelBase -{ - private readonly TaskCompletionSource _completion = new(); - - [ObservableProperty] - private string _key; - - public string HardwareId { get; } - - /// Warum der bisherige Schlüssel nicht taugt; leer beim ersten Fragen. - public string Problem { get; } - - /// Der eingegebene Schlüssel, oder null bei Abbruch. - public Task Result => _completion.Task; - - public LicenseViewModel(string hardwareId, string? problem, string? currentKey) - { - HardwareId = hardwareId; - Problem = problem ?? ""; - _key = currentKey ?? ""; - } - - [RelayCommand] - private void Confirm() - { - var value = Key.Trim(); - - // Leere Eingabe ist kein Abbruch — sonst schließt sich das Fenster, wenn jemand - // versehentlich die Eingabetaste drückt. - if (value.Length == 0) return; - - _completion.TrySetResult(value); - } - - [RelayCommand] - private void Cancel() => _completion.TrySetResult(null); - - /// Schließt der Benutzer das Fenster, gilt das als Abbruch. - public void CancelIfPending() => _completion.TrySetResult(null); -} diff --git a/src/ClawdDotNet.Desktop/ViewModels/LogPageViewModel.cs b/src/ClawdDotNet.Desktop/ViewModels/LogPageViewModel.cs deleted file mode 100644 index a34f12c..0000000 --- a/src/ClawdDotNet.Desktop/ViewModels/LogPageViewModel.cs +++ /dev/null @@ -1,116 +0,0 @@ -using System.Collections.ObjectModel; -using Avalonia.Threading; -using ClawdDotNet.App; -using ClawdDotNet.App.Services; -using ClawdDotNet.Core.Storage; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; - -namespace ClawdDotNet.Desktop.ViewModels; - -/// -/// Live-Ansicht der Logdateien. -/// -/// Der Takt läuft über — das Avalonia-Gegenstück zum -/// System.Windows.Forms.Timer, also auf dem Oberflächenfaden. Für eine Ansicht -/// ist das genau richtig: Das Lesen selbst dauert Millisekunden, und so entfällt jedes -/// Marshalling. Alles, was ohne Fenster laufen muss, liegt dagegen in -/// und taktet dort über PeriodicTimer. -/// -public sealed partial class LogPageViewModel : PageViewModel -{ - /// - /// Obergrenze der angezeigten Zeilen. - /// - /// Ohne Deckel wächst die Liste unbegrenzt — ein Agent, der eine Nacht durchläuft, - /// hinterlässt sonst Hunderttausende Einträge im Speicher, und das Scrollen wird zäh. - /// - private const int MaxLines = 2000; - - private readonly LogTail? _tail; - private readonly DispatcherTimer? _timer; - private readonly string _logDirectory; - - public ObservableCollection Lines { get; } = []; - - public ObservableCollection Modules { get; } = [LocalizationManager.Instance["common.all"]]; - - public IReadOnlyList Levels { get; } = [LocalizationManager.Instance["common.all"], "Info", "Warn", "Error"]; - - [ObservableProperty] - private string _selectedModule = LocalizationManager.Instance["common.all"]; - - [ObservableProperty] - private string _selectedLevel = LocalizationManager.Instance["common.all"]; - - /// - /// Hängt die Ansicht am unteren Ende? Sobald jemand nach oben scrollt, soll nicht - /// weitergesprungen werden — sonst kann man nichts lesen, während etwas läuft. - /// - [ObservableProperty] - private bool _followTail = true; - - public LogPageViewModel(AppHost? host) : base("nav.logs") - { - _logDirectory = host?.LogDirectory ?? ""; - - if (host is null) return; // Entwurfsmodus - - _tail = new LogTail(_logDirectory); - RefreshModules(); - - _timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(500) }; - _timer.Tick += (_, _) => Poll(); - _timer.Start(); - } - - private void Poll() - { - if (_tail is null) return; - - var isAllModule = string.Equals(SelectedModule, LocalizationManager.Instance["common.all"], StringComparison.OrdinalIgnoreCase) || - string.Equals(SelectedModule, "All", StringComparison.OrdinalIgnoreCase) || - string.Equals(SelectedModule, "Alle", StringComparison.OrdinalIgnoreCase); - var module = isAllModule ? null : SelectedModule; - var level = SelectedLevel switch - { - "Info" => LogLevelFilter.Info, - "Warn" => LogLevelFilter.Warn, - "Error" => LogLevelFilter.Error, - _ => LogLevelFilter.All - }; - - foreach (var line in _tail.ReadNew(module, level)) - { - Lines.Add(line); - - // Von vorn kürzen statt am Ende zu deckeln: Das Neueste soll bleiben. - while (Lines.Count > MaxLines) - Lines.RemoveAt(0); - } - } - - [RelayCommand] - private void Clear() => Lines.Clear(); - - [RelayCommand] - private void RefreshModules() - { - if (_tail is null) return; - - var current = SelectedModule; - var allText = LocalizationManager.Instance["common.all"]; - - Modules.Clear(); - Modules.Add(allText); - - foreach (var module in _tail.AvailableModules()) - Modules.Add(module); - - // Auswahl halten, wenn es das Modul noch gibt. - SelectedModule = Modules.Contains(current) ? current : allText; - } - - [RelayCommand] - private void OpenFolder() => SystemShell.OpenFolder(_logDirectory); -} diff --git a/src/ClawdDotNet.Desktop/ViewModels/MainWindowViewModel.cs b/src/ClawdDotNet.Desktop/ViewModels/MainWindowViewModel.cs deleted file mode 100644 index 8003868..0000000 --- a/src/ClawdDotNet.Desktop/ViewModels/MainWindowViewModel.cs +++ /dev/null @@ -1,396 +0,0 @@ -using System.Collections.ObjectModel; -using Avalonia.Threading; -using ClawdDotNet.App; -using ClawdDotNet.Core.Storage; -using ClawdDotNet.Desktop.Services; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; - -// Ohne Alias verweist "App" hier auf ClawdDotNet.Desktop.App, die Anwendungsklasse -// von Avalonia — und nicht auf die gleichnamige Fachschicht. -using AppSettings = ClawdDotNet.App.Settings.AppSettings; - -namespace ClawdDotNet.Desktop.ViewModels; - -/// -/// Das Gerüst des Hauptfensters: Seitenleiste, Kopfzeile, Meldungen, Statusleiste. -/// -/// Die Menüleiste ist entfallen. Der Entwurf kennt keine, und ihre Einträge hatten -/// ohnehin überall sonst schon einen Platz: Der Instanzwechsel sitzt jetzt als eigener -/// Schalter oben in der Seitenleiste, die Ordner-Befehle stehen dort, wo die Ordner -/// gebraucht werden (Logs-Seite, Info-Seite), und „Ansicht" war eine zweite Navigation -/// neben der Navigation. -/// -public sealed partial class MainWindowViewModel : ViewModelBase -{ - private readonly AppHost? _host; - - /// Breite der Seitenleiste, ausgeklappt und eingeklappt (siehe Entwurf). - private const double SidebarWidthExpanded = 240; - private const double SidebarWidthCollapsed = 64; - - [ObservableProperty] - [NotifyPropertyChangedFor(nameof(PageTitle))] - private PageViewModel? _selectedPage; - - [ObservableProperty] - [NotifyPropertyChangedFor(nameof(SidebarWidth))] - [NotifyPropertyChangedFor(nameof(IsSidebarExpanded))] - private bool _isSidebarCollapsed; - - [ObservableProperty] - [NotifyPropertyChangedFor(nameof(ThemeLabel))] - [NotifyPropertyChangedFor(nameof(ThemeIconKey))] - private bool _isDarkTheme; - - // ─── Statusleiste ─── - - [ObservableProperty] - [NotifyPropertyChangedFor(nameof(InstanceStatusLabel))] - private string _instanceName = "—"; - - [ObservableProperty] - private bool _isApiReachable; - - [ObservableProperty] - [NotifyPropertyChangedFor(nameof(ApiStatusDisplay))] - private string _apiStatusText = "unbekannt"; - - public string InstanceStatusLabel => LocalizationManager.Instance.Get("desktop.mainWindow.instanceLabel", InstanceName); - public string ApiStatusDisplay => LocalizationManager.Instance.Get("desktop.mainWindow.apiStatus", ApiStatusText); - - /// Kurzinfo zu Tokens und Kosten der letzten Stunde bzw. 24 Stunden. - [ObservableProperty] - private string _usageText = "—"; - - [ObservableProperty] - private string _usageTooltip = ""; - - [ObservableProperty] - private string _creditsText = "—"; - - /// Alle Bereiche, in der Reihenfolge der Navigation. - public ObservableCollection Pages { get; } = []; - - /// Die Navigation, gruppiert wie im Entwurf. - public ObservableCollection NavGroups { get; } = []; - - /// - /// Instanzübergreifende Hinweise. Bleibt vorerst leer — der Dienst, der Fehler und - /// aufgebrauchte Guthaben anderer Instanzen sieht, existiert noch nicht - /// (siehe Implementierungsleitfaden im Mockup-Verzeichnis). Die Leiste blendet sich - /// aus, solange nichts anliegt, und ist damit heute schon unauffällig richtig. - /// - public ObservableCollection Notifications { get; } = []; - - public bool HasNotifications => Notifications.Count > 0; - - public double SidebarWidth => IsSidebarCollapsed ? SidebarWidthCollapsed : SidebarWidthExpanded; - - public bool IsSidebarExpanded => !IsSidebarCollapsed; - - public string PageTitle => SelectedPage?.Title ?? ""; - - public string ThemeLabel => IsDarkTheme - ? LocalizationManager.Instance["desktop.mainWindow.themeDark"] - : LocalizationManager.Instance["desktop.mainWindow.themeLight"]; - - /// Fusszeile der Seitenleiste. - public string VersionText => $"ClawdDotNet {AppHost.AppVersion} · Avalonia"; - - /// Sonne im Hellmodus, Mond im Dunkelmodus — beides Namen aus Icons.axaml. - public string ThemeIconKey => IsDarkTheme ? "IconMoon" : "IconSun"; - - public event Action? RequestExit; - public event Action? RequestInstanceManagerDialog; - - /// - /// Ob der Instanzwechsel aus diesem Fenster heraus angeboten wird. - /// - /// false, sobald der Instanzmanager diese Instanz führt (#528, E-M2): - /// Dann hält er die Fenster aller Instanzen im Hintergrund und holt das gewünschte - /// nach vorn. Ein Wechsel von hier aus wäre ein Selbst-Neustart und nähme genau die - /// Instanz mit, aus der heraus jemand wechselt. - /// - public bool CanSwitchInstance { get; init; } = true; - - /// Für den Entwurfsmodus des Editors — ohne laufenden Aufbau. - public MainWindowViewModel() : this(null) { } - - public MainWindowViewModel(AppHost? host) - { - _host = host; - - var chat = new ChatPageViewModel(host); - var agents = new AgentsPageViewModel(host); - var tasks = new TasksPageViewModel(host); - var tokens = new TokenUsagePageViewModel(host); - var agentChats = new AgentChatsPageViewModel(host); - var backup = new BackupPageViewModel(host); - var logs = new LogPageViewModel(host); - var settings = new SettingsPageViewModel(host); - var info = new InfoPageViewModel(host); - - foreach (var page in new PageViewModel[] - { chat, agents, tasks, tokens, agentChats, backup, logs, settings, info }) - Pages.Add(page); - - NavGroups.Add(new NavGroupViewModel("desktop.nav.work", - [ - new NavItemViewModel(this, chat, "IconChat"), - new NavItemViewModel(this, agents, "IconAgents"), - new NavItemViewModel(this, tasks, "IconTasks") - ])); - - NavGroups.Add(new NavGroupViewModel("desktop.nav.analytics", - [ - new NavItemViewModel(this, tokens, "IconChart"), - new NavItemViewModel(this, agentChats, "IconAgentChats") - ])); - - NavGroups.Add(new NavGroupViewModel("desktop.nav.system", - [ - new NavItemViewModel(this, backup, "IconBackup"), - new NavItemViewModel(this, logs, "IconLogs"), - new NavItemViewModel(this, settings, "IconSettings"), - new NavItemViewModel(this, info, "IconInfo") - ])); - - LocalizationManager.Instance.LanguageChanged += () => - { - OnPropertyChanged(nameof(PageTitle)); - OnPropertyChanged(nameof(ThemeLabel)); - OnPropertyChanged(nameof(InstanceStatusLabel)); - OnPropertyChanged(nameof(ApiStatusDisplay)); - if (_host is null) - { - InstanceName = LocalizationManager.Instance["desktop.status.design"]; - ApiStatusText = LocalizationManager.Instance["desktop.status.design"]; - } - }; - - // Die Leiste blendet sich aus, solange nichts anliegt — dafür muss die Ansicht - // von Zu- und Abgängen erfahren, nicht nur von der Sammlung selbst. - Notifications.CollectionChanged += (_, _) => OnPropertyChanged(nameof(HasNotifications)); - - SelectedPage = chat; - - if (host is null) - { - InstanceName = "Entwurfsmodus"; - ApiStatusText = "Entwurf"; - UsageText = "1h: 3.240 Tok · 24h: 168.500 Tok"; - CreditsText = "Credits: $41.86 von $100.00"; - - // Zwei Beispielmeldungen, damit die Leiste im Editor sichtbar ist. - Notifications.Add(new NotificationViewModel( - this, isError: true, "sandbox", "OpenRouter-Guthaben aufgebraucht — Agenten pausiert.")); - Notifications.Add(new NotificationViewModel( - this, isError: false, "stock-team", "3 unbehandelte Exceptions in den letzten 15 Minuten.")); - return; - } - - InstanceName = host.Instance.InstanceName; - - IsSidebarCollapsed = host.Settings.AppSettings.SidebarCollapsed; - IsDarkTheme = ThemeManager.IsDarkName(host.Settings.AppSettings.Theme); - ThemeManager.Apply(IsDarkTheme); - ApplyCollapsedToNav(); - - HookStatusService(host); - } - - /// - /// Hängt die Statusleiste an den OpenRouter-Dienst. - /// - /// Der Dienst war fertig und ungenutzt — er lieferte seine Texte bislang an - /// niemanden. OnStatusUpdated kommt vom Hintergrundfaden des - /// PeriodicTimer, deshalb der Wechsel auf den Oberflächenfaden. - /// - private void HookStatusService(AppHost host) - { - if (host.Status is not { } status) - { - ApiStatusText = LocalizationManager.Instance["desktop.status.noApiKey"]; - UsageText = LocalizationManager.Instance["desktop.status.noUsageData"]; - CreditsText = ""; - return; - } - - void Update() - { - IsApiReachable = status.IsApiReachable; - ApiStatusText = status.IsApiReachable - ? LocalizationManager.Instance["desktop.status.reachable"] - : LocalizationManager.Instance["desktop.status.unreachable"]; - UsageText = status.CreditsText; - UsageTooltip = status.CreditsTooltip; - - CreditsText = status.CreditRemaining is { } remaining && status.CreditBalance is { } total - ? LocalizationManager.Instance.Get("desktop.mainWindow.credits", remaining, total) - : LocalizationManager.Instance["desktop.mainWindow.creditsNone"]; - } - - status.OnStatusUpdated += () => Dispatcher.UIThread.Post(Update); - Update(); - } - - partial void OnSelectedPageChanged(PageViewModel? value) - { - foreach (var item in NavGroups.SelectMany(g => g.Items)) - item.IsSelected = ReferenceEquals(item.Page, value); - } - - partial void OnIsSidebarCollapsedChanged(bool value) - { - ApplyCollapsedToNav(); - Persist(s => s.SidebarCollapsed = value); - } - - partial void OnIsDarkThemeChanged(bool value) - { - ThemeManager.Apply(value); - Persist(s => s.Theme = ThemeManager.ToName(value)); - } - - /// - /// Der eingeklappte Zustand steht an jedem Eintrag statt an einer Bindung auf das - /// Elternfenster: Aus einer DataTemplate heraus zurück auf das Fenster zu binden ist - /// mit übersetzten Bindungen jedes Mal ein Ausdruck, den niemand mehr liest. - /// - private void ApplyCollapsedToNav() - { - foreach (var group in NavGroups) - { - group.IsTitleVisible = !IsSidebarCollapsed; - - foreach (var item in group.Items) - item.IsCollapsed = IsSidebarCollapsed; - } - } - - /// - /// Einstellungen sind ein Nebeneffekt der Bedienung, kein eigener Vorgang: Wer die - /// Leiste einklappt, drückt nicht anschließend auf Speichern. Ein Schreibfehler darf - /// die Bedienung deshalb auch nicht unterbrechen. - /// - private void Persist(Action change) - { - if (_host is null) return; - - try - { - change(_host.Settings.AppSettings); - _host.Settings.Save(); - } - catch (Exception) - { - // Der Zustand gilt für diese Sitzung trotzdem — nur eben nicht für die nächste. - } - } - - [RelayCommand] - private void SelectPage(PageViewModel? page) - { - if (page is not null) SelectedPage = page; - } - - [RelayCommand] - private void ToggleSidebar() => IsSidebarCollapsed = !IsSidebarCollapsed; - - [RelayCommand] - private void ToggleTheme() => IsDarkTheme = !IsDarkTheme; - - [RelayCommand] - private void OpenInstanceFolder() - { - if (_host is null) return; - SystemShell.OpenFolder(_host.InstancePath); - } - - [RelayCommand] - private void OpenInstanceManager() => RequestInstanceManagerDialog?.Invoke(); - - [RelayCommand] - private void Exit() => RequestExit?.Invoke(); -} - -/// Eine Gruppe der Navigation („Arbeiten", „Analyse", „System"). -public sealed partial class NavGroupViewModel : ObservableObject -{ - private readonly string _titleKey; - public string Title => LocalizationManager.Instance.Get(_titleKey); - public IReadOnlyList Items { get; } - - /// Im eingeklappten Zustand entfällt die Gruppenüberschrift. - [ObservableProperty] - private bool _isTitleVisible = true; - - public NavGroupViewModel(string titleKey, IReadOnlyList items) - { - _titleKey = titleKey; - Items = items; - LocalizationManager.Instance.LanguageChanged += () => OnPropertyChanged(nameof(Title)); - } -} - -/// -/// Ein Eintrag der Navigation. -/// -/// Der Befehl sitzt am Eintrag selbst und nicht am Fenster: Aus einer DataTemplate -/// heraus über $parent[…] auf einen Befehl des Fensters zu binden funktioniert -/// zwar, ist aber bei übersetzten Bindungen ein Ausdruck mit Typumwandlung, den man beim -/// nächsten Lesen erst wieder entziffern muss. -/// -public sealed partial class NavItemViewModel : ObservableObject -{ - private readonly MainWindowViewModel _owner; - public PageViewModel Page { get; } - public string Title => Page.Title; - - /// Name der Geometrie in Styles/Icons.axaml. - public string IconKey { get; } - - [ObservableProperty] - private bool _isSelected; - - [ObservableProperty] - private bool _isCollapsed; - - public NavItemViewModel(MainWindowViewModel owner, PageViewModel page, string iconKey) - { - _owner = owner; - Page = page; - IconKey = iconKey; - LocalizationManager.Instance.LanguageChanged += () => OnPropertyChanged(nameof(Title)); - } - - [RelayCommand] - private void Select() => _owner.SelectedPage = Page; -} - -/// Eine Zeile der Benachrichtigungsleiste. -public sealed partial class NotificationViewModel( - MainWindowViewModel owner, bool isError, string instanceName, string text) : ObservableObject -{ - public bool IsError { get; } = isError; - public bool IsWarning => !IsError; - public string InstanceName { get; } = instanceName; - public string Text { get; } = text; - - [RelayCommand] - private void Dismiss() => owner.Notifications.Remove(this); -} - -/// Ein Bereich des Hauptfensters. -public abstract partial class PageViewModel : ViewModelBase -{ - private readonly string _titleKey; - public string Title => LocalizationManager.Instance.Get(_titleKey); - - protected PageViewModel(string titleKey) - { - _titleKey = titleKey; - LocalizationManager.Instance.LanguageChanged += () => OnPropertyChanged(nameof(Title)); - } -} diff --git a/src/ClawdDotNet.Desktop/ViewModels/RestoreBackupViewModel.cs b/src/ClawdDotNet.Desktop/ViewModels/RestoreBackupViewModel.cs deleted file mode 100644 index d93bf37..0000000 --- a/src/ClawdDotNet.Desktop/ViewModels/RestoreBackupViewModel.cs +++ /dev/null @@ -1,82 +0,0 @@ -using ClawdDotNet.Core.Backup; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; - -namespace ClawdDotNet.Desktop.ViewModels; - -public sealed record RestoreResultData(string TargetDirectory, string? Passphrase, bool Overwrite); - -public sealed partial class RestoreBackupViewModel : ViewModelBase -{ - private readonly BackupManifest _manifest; - - public string InstanceName => _manifest.InstanceName; - public DateTime CreatedAt => _manifest.CreatedAt; - public int FileCount => _manifest.Files.Count; - public bool NeedsPassphrase => _manifest.HasSecrets; - - public string SecretsDescription => _manifest.HasSecrets - ? $"{_manifest.SecretCount}, passphrase protected" - : _manifest.SecretCount > 0 - ? $"{_manifest.SecretCount} excluded" - : "none"; - - public string InstanceInfoText => string.Format(L["desktop.dialog.backupInstance"], InstanceName); - public string CreatedAtText => string.Format(L["desktop.dialog.backupCreated"], CreatedAt); - public string FileCountText => string.Format(L["desktop.dialog.backupFiles"], FileCount); - public string SecretsText => string.Format(L["desktop.dialog.backupSecrets"], SecretsDescription); - - [ObservableProperty] - private string _targetDirectory = ""; - - [ObservableProperty] - private string _passphrase = ""; - - [ObservableProperty] - private bool _overwrite; - - [ObservableProperty] - private string _statusMessage = ""; - - public RestoreResultData? Result { get; private set; } - - public event Action? CloseRequested; - - public RestoreBackupViewModel() : this(new BackupManifest(), @"C:\Instance_Restored") { } - - public RestoreBackupViewModel(BackupManifest manifest, string suggestedTarget) - { - _manifest = manifest; - TargetDirectory = suggestedTarget; - } - - [RelayCommand] - private void Confirm() - { - if (string.IsNullOrWhiteSpace(TargetDirectory)) - { - StatusMessage = "Please specify a target directory."; - return; - } - - if (NeedsPassphrase && string.IsNullOrEmpty(Passphrase)) - { - StatusMessage = "Please enter the passphrase for protected credentials."; - return; - } - - Result = new RestoreResultData( - TargetDirectory.Trim(), - NeedsPassphrase ? Passphrase : null, - Overwrite); - - CloseRequested?.Invoke(); - } - - [RelayCommand] - private void Cancel() - { - Result = null; - CloseRequested?.Invoke(); - } -} diff --git a/src/ClawdDotNet.Desktop/ViewModels/SettingsPageViewModel.cs b/src/ClawdDotNet.Desktop/ViewModels/SettingsPageViewModel.cs deleted file mode 100644 index adcca0a..0000000 --- a/src/ClawdDotNet.Desktop/ViewModels/SettingsPageViewModel.cs +++ /dev/null @@ -1,227 +0,0 @@ -using ClawdDotNet.App; -using ClawdDotNet.App.Services; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; -using Microsoft.Extensions.Logging; -using ClawdDotNet.Desktop.Services; - -namespace ClawdDotNet.Desktop.ViewModels; - -/// -/// Ansichtsmodell für die Einstellungen-Seite (Anwendungs- und Instanz-Einstellungen). -/// -public sealed partial class SettingsPageViewModel : PageViewModel -{ - private readonly AppHost? _host; - private readonly ILogger? _logger; - - /// Womit die Seite geladen wurde — nur, um eine Änderung zu erkennen. - private string _logDirectoryAtLoad = ""; - - // ─── Allgemein & Pfade ─── - [ObservableProperty] - private string _instancesDirectory = ""; - - [ObservableProperty] - private string _minimumLogLevel = "Info"; - - [ObservableProperty] - private int _maxLogLinesInUi = 2000; - - [ObservableProperty] - private int _logRefreshIntervalMs = 500; - - // ─── API & OpenRouter ─── - [ObservableProperty] - private string _openRouterBaseUrl = "https://openrouter.ai/api/v1/"; - - [ObservableProperty] - private int _statusCheckIntervalSeconds = 60; - - // Die Sicherungs-Einstellungen (Zielordner, Uhrzeit, Anzahl) stehen bewusst - // NICHT hier, sondern allein auf der Sicherungs-Seite. Sie lagen frueher - // doppelt vor: Die Felder waren aus der Ansicht bereits verschwunden, wurden - // aber weiter beim Start gelesen und beim Speichern zurueckgeschrieben - wer - // die Uhrzeit auf der Sicherungs-Seite aenderte und danach hier speicherte, - // bekam den alten Wert zurueck. - // ─── Deploymentcenter ─── - [ObservableProperty] - private string _deploymentcenterUrl = "https://dc.mhdf.de"; - - [ObservableProperty] - private string _deploymentcenterToken = ""; - - [ObservableProperty] - private string _deploymentcenterEnvironment = "production"; - - [ObservableProperty] - private bool _errorReportingEnabled = true; - - [ObservableProperty] - private bool _updateCheckEnabled = true; - - [ObservableProperty] - private string _updateChannel = "prod"; - - // ─── Lizenz ─── - [ObservableProperty] - private string _licenseKey = ""; - - // ─── Instanz-Einstellungen ─── - [ObservableProperty] - private string _instanceName = ""; - - /// - /// Wohin diese Instanz protokolliert. Steht seit #528 (Stufe 1) hier und nicht mehr - /// bei den Anwendungseinstellungen: Ein Verzeichnis für alle hiess, dass in - /// Startup.log abwechselnd zwei Instanzen schrieben, ohne Kennzeichnung, welche - /// gerade spricht. - /// - /// Leer angezeigt heisst leer gemeint — die Vorgabe steht als Hinweis unter - /// dem Feld. Anders als bei der Sicherungsseite wird hier bewusst nicht aufgeloest: - /// Der geltende Ort steht auf der Info-Seite, und ein aufgeloester Pfad im Feld - /// wuerde beim naechsten Speichern festgeschrieben. - /// - [ObservableProperty] - private string _logDirectory = ""; - - /// - /// Ob der Instanzmanager diese Instanz am Laufen hält (#528). - /// - /// Steht hier und nicht beim Manager, weil es eine Eigenschaft dieser Instanz - /// ist — und weil die Instanzdatei dem Instanzprozess gehört: Sie vom Manager - /// schreiben zu lassen, während die Instanz läuft, waeren zwei Schreiber auf einer - /// Datei. Der Manager liest den Schalter nur. - /// - [ObservableProperty] - private bool _autostartByManager; - - [ObservableProperty] - private string _openRouterApiKey = ""; - - [ObservableProperty] - private decimal _instanceDailyCostUsd; - - [ObservableProperty] - private long _instanceDailyTokens; - - [ObservableProperty] - private string _statusText = "Bereit"; - - [ObservableProperty] - private string _selectedLanguage = LocalizationManager.DefaultLanguage; - - public IReadOnlyList AvailableLanguages => LocalizationManager.Instance.AvailableLanguages; - - public LanguageOption? SelectedLanguageOption - { - get => AvailableLanguages.FirstOrDefault(l => l.Code.Equals(SelectedLanguage, StringComparison.OrdinalIgnoreCase)) ?? AvailableLanguages.FirstOrDefault(); - set - { - if (value is not null && value.Code != SelectedLanguage) - { - SelectedLanguage = value.Code; - OnPropertyChanged(); - LocalizationManager.Instance.SetLanguage(value.Code); - } - } - } - - public List LogLevels { get; } = ["Debug", "Info", "Warn", "Error"]; - public List UpdateChannels { get; } = ["prod", "beta", "dev"]; - public List Environments { get; } = ["production", "development", "staging"]; - - public SettingsPageViewModel() : this(null) { } - - public SettingsPageViewModel(AppHost? host) : base("nav.settings") - { - _host = host; - - if (host is not null) - { - _logger = host.LoggerFactory.CreateLogger("ClawdDotNet.Desktop.Settings"); - LoadFromHost(); - } - else - { - StatusText = LocalizationManager.Instance["desktop.status.design"]; - } - } - - [RelayCommand] - private void LoadFromHost() - { - if (_host is null) return; - - var s = _host.Settings.AppSettings; - InstancesDirectory = s.InstancesDirectory; - MinimumLogLevel = s.MinimumLogLevel; - MaxLogLinesInUi = s.MaxLogLinesInUi; - LogRefreshIntervalMs = s.LogRefreshIntervalMs; - OpenRouterBaseUrl = s.OpenRouterBaseUrl; - StatusCheckIntervalSeconds = s.StatusCheckIntervalSeconds; - DeploymentcenterUrl = s.DeploymentcenterUrl; - DeploymentcenterToken = s.DeploymentcenterToken; - DeploymentcenterEnvironment = s.DeploymentcenterEnvironment; - ErrorReportingEnabled = s.ErrorReportingEnabled; - UpdateCheckEnabled = s.UpdateCheckEnabled; - UpdateChannel = s.UpdateChannel; - LicenseKey = s.LicenseKey; - SelectedLanguage = s.Language ?? LocalizationManager.DefaultLanguage; - OnPropertyChanged(nameof(SelectedLanguageOption)); - - var inst = _host.Instance; - InstanceName = inst.InstanceName; - LogDirectory = inst.LogDirectory; - AutostartByManager = inst.AutostartByManager; - _logDirectoryAtLoad = inst.LogDirectory; - OpenRouterApiKey = inst.OpenRouterApiKey; - InstanceDailyCostUsd = inst.Budget.DailyCostUsd; - InstanceDailyTokens = inst.Budget.DailyTokens; - } - - [RelayCommand] - private void SaveSettings() - { - if (_host is null) return; - - var s = _host.Settings.AppSettings; - s.InstancesDirectory = InstancesDirectory.Trim(); - s.MinimumLogLevel = MinimumLogLevel; - s.MaxLogLinesInUi = MaxLogLinesInUi; - s.LogRefreshIntervalMs = LogRefreshIntervalMs; - s.OpenRouterBaseUrl = OpenRouterBaseUrl.Trim(); - s.StatusCheckIntervalSeconds = StatusCheckIntervalSeconds; - s.DeploymentcenterUrl = DeploymentcenterUrl.Trim(); - s.DeploymentcenterToken = DeploymentcenterToken.Trim(); - s.DeploymentcenterEnvironment = DeploymentcenterEnvironment.Trim(); - s.ErrorReportingEnabled = ErrorReportingEnabled; - s.UpdateCheckEnabled = UpdateCheckEnabled; - s.UpdateChannel = UpdateChannel; - s.LicenseKey = LicenseKey.Trim(); - s.Language = SelectedLanguage; - - _host.Settings.Save(); - LocalizationManager.Instance.SetLanguage(SelectedLanguage); - - var inst = _host.Instance; - inst.InstanceName = InstanceName.Trim(); - inst.LogDirectory = LogDirectory.Trim(); - inst.AutostartByManager = AutostartByManager; - inst.OpenRouterApiKey = OpenRouterApiKey.Trim(); - inst.Budget.DailyCostUsd = InstanceDailyCostUsd; - inst.Budget.DailyTokens = InstanceDailyTokens; - - _host.SaveInstance(new InstanceChange(InstanceChangeKind.Settings)); - - _logger?.LogInformation("Settings and instance configuration saved."); - - // Das Protokoll-Verzeichnis greift erst beim naechsten Start: Die - // Protokollierung steht seit dem Aufbau des AppHost und schreibt bereits. - StatusText = string.Equals(inst.LogDirectory, _logDirectoryAtLoad, StringComparison.Ordinal) - ? LocalizationManager.Instance["desktop.settings.saved"] - : LocalizationManager.Instance["desktop.settings.savedLogRestart"]; - - _logDirectoryAtLoad = inst.LogDirectory; - } -} diff --git a/src/ClawdDotNet.Desktop/ViewModels/TasksPageViewModel.cs b/src/ClawdDotNet.Desktop/ViewModels/TasksPageViewModel.cs deleted file mode 100644 index 9051afc..0000000 --- a/src/ClawdDotNet.Desktop/ViewModels/TasksPageViewModel.cs +++ /dev/null @@ -1,398 +0,0 @@ -using System.Collections.ObjectModel; -using Avalonia.Threading; -using ClawdDotNet.App; -using ClawdDotNet.App.Models; -using ClawdDotNet.App.Services; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; -using Microsoft.Extensions.Logging; - -namespace ClawdDotNet.Desktop.ViewModels; - -public sealed record JobDisplayItemViewModel( - string JobType, - string JobId, - string AgentId, - string AgentName, - string ToolName, - string CronExpression, - string TaskMessage, - bool RunOnStart, - string NextRun, - string LastRun, - string LastStatus, - string Status -); - -/// Die drei Ansichten der Aufgaben-Seite. -public enum TasksTab -{ - Jobs, - Services, - History -} - -public sealed record ServiceDisplayItemViewModel( - string ServiceId, - string Name, - string Type, - int Port, - string Status, - string Description -); - -/// -/// Ansichtsmodell für die Aufgaben-Seite (Jobs, Dienste, Verlauf). -/// -public sealed partial class TasksPageViewModel : PageViewModel -{ - private readonly AppHost? _host; - private readonly ILogger? _logger; - - public ObservableCollection JobEntries { get; } = []; - public ObservableCollection ServiceEntries { get; } = []; - public ObservableCollection JobHistoryEntries { get; } = []; - - [ObservableProperty] - private JobDisplayItemViewModel? _selectedJob; - - [ObservableProperty] - private ServiceDisplayItemViewModel? _selectedService; - - [ObservableProperty] - private string _statusText = "Bereit"; - - [ObservableProperty] - private bool _isRunningJob; - - /// - /// Der Entwurf ersetzt die Registerkarten durch eine Segmentleiste. Fachlich ist das - /// dasselbe: eine von drei Ansichten. Die drei Kennzeichen darunter gibt es, weil - /// eine Bindung „Ist dieser Wert gleich Services?" in AXAML sonst jedes Mal einen - /// Konverter mit Parameter bräuchte. - /// - [ObservableProperty] - [NotifyPropertyChangedFor(nameof(IsJobsTab))] - [NotifyPropertyChangedFor(nameof(IsServicesTab))] - [NotifyPropertyChangedFor(nameof(IsHistoryTab))] - private TasksTab _selectedTab = TasksTab.Jobs; - - public bool IsJobsTab => SelectedTab == TasksTab.Jobs; - public bool IsServicesTab => SelectedTab == TasksTab.Services; - public bool IsHistoryTab => SelectedTab == TasksTab.History; - - public event Func>? RequestAddJobDialog; - public event Func>? RequestAddServiceDialog; - - public TasksPageViewModel() : this(null) { } - - public TasksPageViewModel(AppHost? host) : base("nav.tasks") - { - _host = host; - - if (host is not null) - { - _logger = host.LoggerFactory.CreateLogger("ClawdDotNet.Desktop.Tasks"); - - host.ServiceAdmin.EnsureBuiltIns(); - RefreshJobList(); - RefreshServiceList(); - RefreshJobHistory(); - - // Auch die Weboberflaeche legt Jobs und Dienste an. Das Ereignis kommt auf - // dem Faden des Verursachers, deshalb ueber den Dispatcher. - // - // Kein Abmelden: Diese Seite lebt so lange wie die Anwendung. - host.InstanceChanged += change => Dispatcher.UIThread.Post(() => - { - switch (change.Kind) - { - case InstanceChangeKind.Jobs: - case InstanceChangeKind.Agents: - // Auch bei Agenten: Verschwindet ein Agent, verschwinden seine - // geplanten Laeufe mit ihm. - RefreshJobList(); - break; - - case InstanceChangeKind.Services: - RefreshServiceList(); - break; - } - }); - } - else - { - StatusText = LocalizationManager.Instance["desktop.status.design"]; - } - } - - [RelayCommand] - private void RefreshJobList() - { - var previous = SelectedJob?.JobId; - - JobEntries.Clear(); - if (_host is null) return; - - foreach (var job in _host.JobAdmin.List()) - JobEntries.Add(ToDisplayItem(job, _host.Runs.LastRun(job.JobId))); - - SelectedJob = JobEntries.FirstOrDefault(j => j.JobId == previous); - } - - /// - /// Formt einen geplanten Lauf für die Anzeige um. - /// - /// Die Fachschicht liefert Zeitpunkte als ; wie sie - /// aussehen und was an ihrer Stelle steht, wenn es keinen gibt, entscheidet die - /// Anzeige. Deshalb steht das Gedankenstrich-Zeichen hier und nicht dort. - /// - private static JobDisplayItemViewModel ToDisplayItem(JobSummary job, DateTime? lastRun) - { - var isToolJob = job.Kind == JobKind.ToolJob; - - var nextRun = !job.CronValid - ? "Ungültig" - : job.NextRunUtc?.ToLocalTime().ToString("yyyy-MM-dd HH:mm") ?? "—"; - - return new JobDisplayItemViewModel( - isToolJob ? "Tool Job" : "Agent Wakeup", - job.JobId, - job.AgentId, - job.AgentName, - isToolJob ? job.ToolName : "—", - job.Cron, - job.Message, - job.RunOnStart, - nextRun, - lastRun?.ToString("yyyy-MM-dd HH:mm:ss") ?? "—", - "—", - job.Enabled - ? "Aktiv" - : isToolJob ? "Deaktiviert" : "Inaktiv"); - } - - [RelayCommand] - private void RefreshServiceList() - { - var previous = SelectedService?.ServiceId; - - ServiceEntries.Clear(); - if (_host is null) return; - - foreach (var svc in _host.Instance.Services) - { - ServiceEntries.Add(new ServiceDisplayItemViewModel( - svc.ServiceId, - svc.Name, - svc.Type, - svc.Port, - svc.Enabled ? "Bereit" : "Deaktiviert", - svc.Description - )); - } - - SelectedService = ServiceEntries.FirstOrDefault(s => s.ServiceId == previous); - } - - [RelayCommand] - private void RefreshJobHistory() - { - JobHistoryEntries.Clear(); - if (_host is null) return; - - foreach (var entry in _host.Runs.History.GetAll().Take(200)) - JobHistoryEntries.Add(entry); - } - - [RelayCommand] - private async Task AddJobAsync() - { - if (_host is null || RequestAddJobDialog is null) return; - - var vm = new AddJobViewModel(_host.Instance.Agents); - var result = await RequestAddJobDialog(vm); - if (result is null) return; - - var outcome = _host.JobAdmin.Add(ToDefinition(result)); - StatusText = outcome.Message; - - if (outcome.Ok) - _logger?.LogInformation("Geplanter Lauf hinzugefügt: Agent={Agent}, Cron={Cron}", - result.AgentId, result.CronExpression); - - RefreshJobList(); - } - - /// Übersetzt das Ergebnis des Dialogs in das, womit die Fachschicht arbeitet. - private static JobDefinition ToDefinition(AddJobResultData result) - => new( - result.AgentId, - result.IsToolJob ? JobKind.ToolJob : JobKind.AgentWakeup, - result.ToolName, - result.JobTypeId, - result.CronExpression, - result.TaskMessage, - result.RunOnStart); - - [RelayCommand] - private async Task EditJobAsync() - { - if (_host is null || SelectedJob is null || RequestAddJobDialog is null) return; - - var entry = SelectedJob; - var agent = _host.Instance.Agents.FirstOrDefault(a => a.AgentId == entry.AgentId); - if (agent is null) return; - - var isToolJob = entry.JobType == "Tool Job"; - var vm = new AddJobViewModel(_host.Instance.Agents) - { - SelectedAgent = agent, - IsToolJob = isToolJob, - SelectedToolName = isToolJob ? entry.ToolName : "FileRW", - JobTypeId = isToolJob ? entry.TaskMessage : "PollJob", - CronExpression = entry.CronExpression, - TaskMessage = isToolJob ? "" : entry.TaskMessage, - RunOnStart = entry.RunOnStart - }; - - var result = await RequestAddJobDialog(vm); - if (result is null) return; - - StatusText = _host.JobAdmin.Update(entry.JobId, ToDefinition(result)).Message; - RefreshJobList(); - } - - [RelayCommand] - private void RemoveJob() - { - if (_host is null || SelectedJob is null) return; - - var entry = SelectedJob; - - StatusText = _host.JobAdmin.Remove( - entry.AgentId, - entry.JobId, - entry.JobType == "Tool Job" ? JobKind.ToolJob : JobKind.AgentWakeup).Message; - - RefreshJobList(); - } - - [RelayCommand] - private async Task RunJobNowAsync() - { - if (_host is null || SelectedJob is null) return; - - var entry = SelectedJob; - var isToolJob = entry.JobType == "Tool Job"; - - IsRunningJob = true; - StatusText = $"Führe Job für '{entry.AgentName}' aus…"; - - try - { - var outcome = isToolJob - ? await _host.Runs.RunToolJobAsync(entry.AgentId, entry.JobId, CancellationToken.None) - : await _host.Runs.RunAgentAsync(entry.AgentId, entry.TaskMessage, CancellationToken.None); - - StatusText = outcome.Message; - - if (!outcome.Ok) - _logger?.LogWarning("Job-Ausführung fehlgeschlagen: {Grund}", outcome.Message); - - RefreshJobList(); - RefreshJobHistory(); - } - finally - { - IsRunningJob = false; - } - } - - [RelayCommand] - private async Task AddServiceAsync() - { - if (_host is null || RequestAddServiceDialog is null) return; - - var vm = new AddServiceViewModel(); - var result = await RequestAddServiceDialog(vm); - if (result is null) return; - - StatusText = _host.ServiceAdmin.Add(new NewService( - result.ServiceName, - result.ServiceType, - result.ServicePort, - result.ServiceDescription)).Message; - - RefreshServiceList(); - } - - [RelayCommand] - private void RemoveService() - { - if (_host is null || SelectedService is null) return; - - StatusText = _host.ServiceAdmin.Remove(SelectedService.ServiceId).Message; - RefreshServiceList(); - } - - /// - /// Schaltet einen Job an oder ab, ohne ihn zu entfernen — im Entwurf die neue - /// Schaltfläche „Aktivieren/Deaktivieren" in der Werkzeugleiste. - /// - /// Gilt nur für Tool-Jobs: SchedulerConfig hat keinen solchen Schalter, - /// ein Agent-Wakeup existiert oder existiert nicht. Ihn hier zu ergänzen wäre keine - /// Oberflächenarbeit — der Scanner müsste den Schalter erst einmal lesen, sonst liefe - /// ein „deaktivierter" Wakeup munter weiter. - /// - [RelayCommand] - private void ToggleJobEnabled() - { - if (_host is null || SelectedJob is null) return; - - var entry = SelectedJob; - - StatusText = _host.JobAdmin - .SetEnabled(entry.AgentId, entry.JobId, enabled: entry.Status != "Aktiv").Message; - - RefreshJobList(); - - // Die Auswahl geht beim Neuaufbau der Liste verloren — sie wieder zu setzen - // erspart es, für zwei Schaltvorgänge zweimal dieselbe Zeile anzuklicken. - SelectedJob = JobEntries.FirstOrDefault(j => j.JobId == entry.JobId); - } - - /// - /// Aktiviert bzw. deaktiviert einen Dienst. - /// - /// Bewusst nicht „Start"/„Stop" genannt, auch wenn der Entwurf das so zeigt: - /// Umgelegt wird das Kennzeichen Enabled in der Instanzkonfiguration. Ein - /// laufender Dienstprozess wird davon nicht angehalten — eine Schaltfläche „Stop", - /// nach der etwas weiterläuft, wäre schlimmer als gar keine. - /// - [RelayCommand] - private void ToggleServiceEnabled() - { - if (_host is null || SelectedService is null) return; - - var id = SelectedService.ServiceId; - - StatusText = _host.ServiceAdmin - .SetEnabled(id, enabled: SelectedService.Status != "Bereit").Message; - - RefreshServiceList(); - SelectedService = ServiceEntries.FirstOrDefault(s => s.ServiceId == id); - } - - [RelayCommand] - private void SelectTab(string? tab) - { - SelectedTab = tab switch - { - "Services" => TasksTab.Services, - "History" => TasksTab.History, - _ => TasksTab.Jobs - }; - } - -} diff --git a/src/ClawdDotNet.Desktop/ViewModels/TokenUsagePageViewModel.cs b/src/ClawdDotNet.Desktop/ViewModels/TokenUsagePageViewModel.cs deleted file mode 100644 index b6068b9..0000000 --- a/src/ClawdDotNet.Desktop/ViewModels/TokenUsagePageViewModel.cs +++ /dev/null @@ -1,201 +0,0 @@ -using System.Collections.ObjectModel; -using ClawdDotNet.App; -using ClawdDotNet.App.Services; -using ClawdDotNet.Core.Accounting; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; - -namespace ClawdDotNet.Desktop.ViewModels; - -/// Ein Balken des Wochendiagramms. -public sealed class TokenDayItem -{ - public required string DayLabel { get; init; } - public required string TokensLabel { get; init; } - public required int Tokens { get; init; } - - /// - /// Höhe in Bildpunkten, nicht in Prozent: Ein Balken kann sich nicht auf die Höhe - /// seines Elternteils beziehen, ohne dass die Zeile eine feste Höhe bekommt — und - /// eine feste Höhe im Ansichtsmodell auszurechnen ist ehrlicher als eine, die in - /// drei Bindungen verteilt steht. - /// - public required double BarHeight { get; init; } -} - -/// Eine Zeile der Aufschlüsselung nach Agent und Modell. -public sealed class TokenAgentItem -{ - public required string AgentName { get; init; } - public required string Model { get; init; } - public required string TokensLabel { get; init; } - public required string CostLabel { get; init; } - public required int Runs { get; init; } -} - -/// -/// Tokennutzung der letzten sieben Tage. -/// -/// Liest aus — dieselbe Quelle, aus der die -/// Tagesbudgets bedient werden. Kein Diagramm-Paket: Der Entwurf zeigt sieben Balken und -/// eine Tabelle, und dafür genügen Rechtecke mit ausgerechneter Höhe. Eine Bibliothek -/// dafür wäre 8 MB Abhängigkeit für sieben Rechtecke. -/// -public sealed partial class TokenUsagePageViewModel : PageViewModel -{ - /// Höhe der Diagrammfläche in Bildpunkten (siehe Entwurf: 160 px inkl. Beschriftung). - private const double ChartHeight = 130; - - /// Wie viele Läufe für die Aufschlüsselung herangezogen werden. - private const int RecentRunLimit = 1000; - - private const int Days = 7; - - private readonly AppHost? _host; - - public ObservableCollection Days7 { get; } = []; - public ObservableCollection ByAgent { get; } = []; - - [ObservableProperty] - private string _totalTokens = "—"; - - [ObservableProperty] - private string _totalCost = "—"; - - [ObservableProperty] - private string _totalRuns = "—"; - - [ObservableProperty] - private string _statusText = ""; - - [ObservableProperty] - private bool _isEmpty = true; - - public TokenUsagePageViewModel() : this(null) { } - - public TokenUsagePageViewModel(AppHost? host) : base("nav.usage") - { - _host = host; - - if (host?.Usage is null) - { - StatusText = host is null - ? "Design mode" - : "No usage database for this instance."; - return; - } - - // Nicht abwarten: Der Aufbau des Fensters darf nicht auf eine Datenbankabfrage - // warten. Die Seite füllt sich, sobald die Zahlen da sind. - _ = RefreshAsync(); - } - - [RelayCommand] - private async Task RefreshAsync() - { - if (_host?.Usage is not { } usage) return; - - try - { - var today = DateOnly.FromDateTime(DateTime.Now); - var daily = new List(Days); - - for (var offset = Days - 1; offset >= 0; offset--) - daily.Add(await usage.GetDailyAsync(today.AddDays(-offset), "", CancellationToken.None)); - - var recent = await usage.GetRecentAsync(RecentRunLimit, CancellationToken.None); - - var since = DateTime.Now.Date.AddDays(-(Days - 1)); - var window = recent.Where(r => r.OccurredAt >= since).ToArray(); - - BuildChart(daily); - BuildBreakdown(window); - BuildTotals(daily, window); - } - catch (Exception ex) - { - StatusText = $"Verbrauchsdaten konnten nicht gelesen werden: {ex.Message}"; - } - } - - private void BuildChart(IReadOnlyList daily) - { - Days7.Clear(); - - // Ohne Höchstwert gäbe es keinen Maßstab; ohne die Untergrenze 1 eine Division - // durch null an dem Tag, an dem noch nichts gelaufen ist. - var max = Math.Max(1, daily.Max(d => d.TotalTokens)); - - foreach (var day in daily) - { - Days7.Add(new TokenDayItem - { - DayLabel = day.Date.ToString("ddd"), - Tokens = day.TotalTokens, - TokensLabel = day.TotalTokens >= 1000 - ? $"{day.TotalTokens / 1000d:0.#}k" - : day.TotalTokens.ToString("N0"), - - // Mindestens ein Pixel, damit ein Tag mit wenigen Tokens nicht wie ein - // Tag ohne Läufe aussieht. - BarHeight = Math.Max(1, day.TotalTokens / (double)max * ChartHeight) - }); - } - } - - private void BuildBreakdown(IReadOnlyList runs) - { - ByAgent.Clear(); - - var names = _host?.Instance.Agents - .ToDictionary(a => a.AgentId, a => a.DisplayName, StringComparer.OrdinalIgnoreCase) - ?? []; - - var groups = runs - .GroupBy(r => (r.AgentId, r.Model)) - .OrderByDescending(g => g.Sum(r => r.PromptTokens + r.CompletionTokens)); - - foreach (var group in groups) - { - var (agentId, model) = group.Key; - var tokens = group.Sum(r => r.PromptTokens + r.CompletionTokens); - var cost = group.Sum(r => r.CostUsd); - var incomplete = group.Any(r => !r.CostIsKnown); - - ByAgent.Add(new TokenAgentItem - { - AgentName = names.TryGetValue(agentId, out var name) ? name : agentId, - Model = model, - TokensLabel = tokens.ToString("N0"), - CostLabel = FormatCost(cost, incomplete), - Runs = group.Count() - }); - } - } - - private void BuildTotals(IReadOnlyList daily, IReadOnlyList runs) - { - var tokens = daily.Sum(d => d.TotalTokens); - var cost = daily.Sum(d => d.CostUsd); - var incomplete = daily.Any(d => !d.CostIsComplete); - - TotalTokens = tokens.ToString("N0"); - TotalCost = FormatCost(cost, incomplete); - TotalRuns = daily.Sum(d => d.RunCount).ToString("N0"); - - IsEmpty = tokens == 0 && runs.Count == 0; - StatusText = IsEmpty ? LocalizationManager.Instance["desktop.usage.empty"] : ""; - } - - /// - /// Kosten in Euro, wie in der Statusleiste — mit demselben Kurs aus - /// . Das Zeichen ⚠ steht für Läufe, - /// deren Modellpreise nicht vorlagen: Die Summe ist dann zu niedrig, und das soll man - /// ihr ansehen. - /// - private static string FormatCost(decimal usd, bool incomplete) - { - var eur = (double)usd * OpenRouterStatusService.UsdToEur; - return incomplete ? $"{eur:F2} € ⚠" : $"{eur:F2} €"; - } -} diff --git a/src/ClawdDotNet.Desktop/ViewModels/ToolSettingsViewModel.cs b/src/ClawdDotNet.Desktop/ViewModels/ToolSettingsViewModel.cs deleted file mode 100644 index 0260670..0000000 --- a/src/ClawdDotNet.Desktop/ViewModels/ToolSettingsViewModel.cs +++ /dev/null @@ -1,221 +0,0 @@ -using ClawdDotNet.Models; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; - -namespace ClawdDotNet.Desktop.ViewModels; - -public sealed partial class ToolSettingsViewModel : ViewModelBase -{ - public string ToolName { get; } - public object? SettingsObject { get; } - - // FTP - [ObservableProperty] private string _ftpHost = ""; - [ObservableProperty] private int _ftpPort = 21; - [ObservableProperty] private string _ftpUsername = ""; - [ObservableProperty] private string _ftpPassword = ""; - [ObservableProperty] private string _ftpRootPath = "./data/"; - - // Mail - [ObservableProperty] private string _mailUsername = ""; - [ObservableProperty] private string _mailPassword = ""; - [ObservableProperty] private string _mailImapHost = ""; - [ObservableProperty] private int _mailImapPort = 993; - [ObservableProperty] private string _mailSmtpHost = ""; - [ObservableProperty] private int _mailSmtpPort = 587; - [ObservableProperty] private string _mailAllowedRecipients = ""; - - // Database - [ObservableProperty] private DatabaseType _dbType = DatabaseType.MySql; - [ObservableProperty] private string _dbConnectionString = ""; - [ObservableProperty] private DatabaseAccessLevel _dbAccessLevel = DatabaseAccessLevel.ReadOnly; - [ObservableProperty] private string _dbAllowedTables = ""; - - // Telegram - [ObservableProperty] private string _telegramBotToken = ""; - [ObservableProperty] private string _telegramDefaultChatId = ""; - [ObservableProperty] private string _telegramAllowedChatIds = ""; - - // DirectAPI - [ObservableProperty] private string _directApiDefaultProvider = "twelvedata"; - [ObservableProperty] private int _directApiCacheTtlSeconds = 60; - [ObservableProperty] private string _directApiTwelveDataKey = ""; - [ObservableProperty] private string _directApiAlphaVantageKey = ""; - - // WebFetch - [ObservableProperty] private string _webFetchAllowedDomains = ""; - [ObservableProperty] private int _webFetchMaxResponseKb = 512; - [ObservableProperty] private string _webFetchUserAgent = "ClawdDotNet-Agent/1.0"; - - // SocialMediaManager - [ObservableProperty] private string _smmXApiKey = ""; - [ObservableProperty] private string _smmXWatchAccounts = ""; - [ObservableProperty] private string _smmRedditWatchSubreddits = ""; - [ObservableProperty] private int _smmRedditPostLimit = 15; - [ObservableProperty] private string _smmOpenRouterApiKey = ""; - [ObservableProperty] private string _smmSttModel = "openai/whisper-1"; - [ObservableProperty] private string _smmYoutubeChannels = ""; - - // FileRW - [ObservableProperty] private string _fileRwPersonalAllowedExtensions = ".txt,.json,.md,.html,.js,.css"; - [ObservableProperty] private FileRWAccessLevel _fileRwSharedAccessLevel = FileRWAccessLevel.Denied; - [ObservableProperty] private string _fileRwSharedAllowedExtensions = ".txt,.json,.md"; - [ObservableProperty] private string _fileRwProtectedPaths = "stocks/"; - - public List DbTypes { get; } = [DatabaseType.MySql, DatabaseType.Postgres, DatabaseType.MsSql, DatabaseType.MongoDb]; - public List DbAccessLevels { get; } = [DatabaseAccessLevel.ReadOnly, DatabaseAccessLevel.ReadWrite, DatabaseAccessLevel.Admin]; - public List FileRwAccessLevels { get; } = [FileRWAccessLevel.Denied, FileRWAccessLevel.Read, FileRWAccessLevel.ReadWrite, FileRWAccessLevel.Admin]; - - public Dictionary? Result { get; private set; } - public event Action? CloseRequested; - - public ToolSettingsViewModel() : this("FTP", new()) { } - - public ToolSettingsViewModel(string toolName, Dictionary config) - { - ToolName = toolName; - SettingsObject = ToolSettingsFactory.CreateViewModel(toolName, config); - - switch (SettingsObject) - { - case FTPToolSettings ftp: - FtpHost = ftp.Host; - FtpPort = ftp.Port; - FtpUsername = ftp.Username; - FtpPassword = ftp.Password; - FtpRootPath = ftp.RootPath; - break; - - case MailToolSettings mail: - MailUsername = mail.Username; - MailPassword = mail.Password; - MailImapHost = mail.ImapHost; - MailImapPort = mail.ImapPort; - MailSmtpHost = mail.SmtpHost; - MailSmtpPort = mail.SmtpPort; - MailAllowedRecipients = mail.AllowedRecipients; - break; - - case DatabaseToolSettings db: - DbType = db.Type; - DbConnectionString = db.ConnectionString; - DbAccessLevel = db.AccessLevel; - DbAllowedTables = db.AllowedTables; - break; - - case TelegramToolSettings tg: - TelegramBotToken = tg.BotToken; - TelegramDefaultChatId = tg.DefaultChatId; - TelegramAllowedChatIds = tg.AllowedChatIds; - break; - - case DirectAPIToolSettings dapi: - DirectApiDefaultProvider = dapi.DefaultProvider; - DirectApiCacheTtlSeconds = dapi.CacheTtlSeconds; - DirectApiTwelveDataKey = dapi.TwelveDataKey; - DirectApiAlphaVantageKey = dapi.AlphaVantageKey; - break; - - case WebFetchToolSettings wf: - WebFetchAllowedDomains = wf.AllowedDomains; - WebFetchMaxResponseKb = wf.MaxResponseKb; - WebFetchUserAgent = wf.UserAgent; - break; - - case SocialMediaManagerToolSettings smm: - SmmXApiKey = smm.XApiKey; - SmmXWatchAccounts = smm.XWatchAccounts; - SmmRedditWatchSubreddits = smm.RedditWatchSubreddits; - SmmRedditPostLimit = smm.RedditPostLimit; - SmmOpenRouterApiKey = smm.OpenRouterApiKey; - SmmSttModel = smm.STTModel; - SmmYoutubeChannels = smm.YoutubeChannels; - break; - - case FileRWToolSettings frw: - FileRwPersonalAllowedExtensions = frw.PersonalAllowedExtensions; - FileRwSharedAccessLevel = frw.SharedAccessLevel; - FileRwSharedAllowedExtensions = frw.SharedAllowedExtensions; - FileRwProtectedPaths = frw.ProtectedPaths; - break; - } - } - - [RelayCommand] - private void Confirm() - { - switch (SettingsObject) - { - case FTPToolSettings ftp: - ftp.Host = FtpHost; - ftp.Port = FtpPort; - ftp.Username = FtpUsername; - ftp.Password = FtpPassword; - ftp.RootPath = FtpRootPath; - break; - - case MailToolSettings mail: - mail.Username = MailUsername; - mail.Password = MailPassword; - mail.ImapHost = MailImapHost; - mail.ImapPort = MailImapPort; - mail.SmtpHost = MailSmtpHost; - mail.SmtpPort = MailSmtpPort; - mail.AllowedRecipients = MailAllowedRecipients; - break; - - case DatabaseToolSettings db: - db.Type = DbType; - db.ConnectionString = DbConnectionString; - db.AccessLevel = DbAccessLevel; - db.AllowedTables = DbAllowedTables; - break; - - case TelegramToolSettings tg: - tg.BotToken = TelegramBotToken; - tg.DefaultChatId = TelegramDefaultChatId; - tg.AllowedChatIds = TelegramAllowedChatIds; - break; - - case DirectAPIToolSettings dapi: - dapi.DefaultProvider = DirectApiDefaultProvider; - dapi.CacheTtlSeconds = DirectApiCacheTtlSeconds; - dapi.TwelveDataKey = DirectApiTwelveDataKey; - dapi.AlphaVantageKey = DirectApiAlphaVantageKey; - break; - - case WebFetchToolSettings wf: - wf.AllowedDomains = WebFetchAllowedDomains; - wf.MaxResponseKb = WebFetchMaxResponseKb; - wf.UserAgent = WebFetchUserAgent; - break; - - case SocialMediaManagerToolSettings smm: - smm.XApiKey = SmmXApiKey; - smm.XWatchAccounts = SmmXWatchAccounts; - smm.RedditWatchSubreddits = SmmRedditWatchSubreddits; - smm.RedditPostLimit = SmmRedditPostLimit; - smm.OpenRouterApiKey = SmmOpenRouterApiKey; - smm.STTModel = SmmSttModel; - smm.YoutubeChannels = SmmYoutubeChannels; - break; - - case FileRWToolSettings frw: - frw.PersonalAllowedExtensions = FileRwPersonalAllowedExtensions; - frw.SharedAccessLevel = FileRwSharedAccessLevel; - frw.SharedAllowedExtensions = FileRwSharedAllowedExtensions; - frw.ProtectedPaths = FileRwProtectedPaths; - break; - } - - Result = ToolSettingsFactory.ToConfig(ToolName, SettingsObject) ?? new(); - CloseRequested?.Invoke(); - } - - [RelayCommand] - private void Cancel() - { - Result = null; - CloseRequested?.Invoke(); - } -} diff --git a/src/ClawdDotNet.Desktop/ViewModels/ViewModelBase.cs b/src/ClawdDotNet.Desktop/ViewModels/ViewModelBase.cs deleted file mode 100644 index 0b15a99..0000000 --- a/src/ClawdDotNet.Desktop/ViewModels/ViewModelBase.cs +++ /dev/null @@ -1,22 +0,0 @@ -using ClawdDotNet.Desktop.Services; -using CommunityToolkit.Mvvm.ComponentModel; - -namespace ClawdDotNet.Desktop.ViewModels; - -/// -/// Grundlage aller Ansichtsmodelle. -/// -/// aus dem CommunityToolkit bringt -/// INotifyPropertyChanged samt Quelltextgenerator mit — aus -/// [ObservableProperty] private string _name; wird die vollständige Eigenschaft -/// mit Benachrichtigung. Das spart gegenüber der WinForms-Fassung, in der die -/// Oberfläche bei jeder Änderung von Hand nachgezogen wurde -/// (38 Stellen mit Invoke/BeginInvoke). -/// -/// macht die Sprachpakete in jeder Ansicht als -/// {Binding L[schluessel]} erreichbar. -/// -public abstract class ViewModelBase : ObservableObject -{ - public LocalizationManager L => LocalizationManager.Instance; -} diff --git a/src/ClawdDotNet.Desktop/Views/AddAgentWindow.axaml b/src/ClawdDotNet.Desktop/Views/AddAgentWindow.axaml deleted file mode 100644 index 4704a23..0000000 --- a/src/ClawdDotNet.Desktop/Views/AddAgentWindow.axaml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/ClawdDotNet.Desktop/Views/AgentsPageView.axaml.cs b/src/ClawdDotNet.Desktop/Views/AgentsPageView.axaml.cs deleted file mode 100644 index 2cc01f3..0000000 --- a/src/ClawdDotNet.Desktop/Views/AgentsPageView.axaml.cs +++ /dev/null @@ -1,101 +0,0 @@ -using Avalonia.Controls; -using Avalonia.Controls.Primitives; -using ClawdDotNet.Desktop.ViewModels; - -namespace ClawdDotNet.Desktop.Views; - -public partial class AgentsPageView : UserControl -{ - private AgentsPageViewModel? _viewModel; - - public AgentsPageView() - { - InitializeComponent(); - - // Ein Zug am Teiler ist erst zu Ende, wenn die Maus losgelassen wird. Waehrend - // des Ziehens zu speichern hiesse, fuer eine Bewegung ein paar Dutzend Mal die - // Einstellungsdatei zu schreiben. - TopSplitter.DragCompleted += (_, _) => SaveSplits(); - BottomSplitter.DragCompleted += (_, _) => SaveSplits(); - VerticalSplitter.DragCompleted += (_, _) => SaveSplits(); - } - - protected override void OnDataContextChanged(EventArgs e) - { - base.OnDataContextChanged(e); - - if (DataContext is not AgentsPageViewModel vm) return; - - _viewModel = vm; - vm.RequestAddAgentDialog += OnRequestAddAgentDialog; - vm.RequestTextEditorDialog += OnRequestTextEditorDialog; - - ApplySavedSplits(vm); - } - - /// - /// Setzt die gespeicherten Teilerstellungen. - /// - /// Von Hand und nicht per Bindung: und - /// liegen nicht im Sichtbarkeitsbaum und erben deshalb - /// keinen DataContext. Eine Bindung auf ihre Breite bliebe ohne Wirkung — und zwar - /// ohne Fehlermeldung. - /// - private void ApplySavedSplits(AgentsPageViewModel vm) - { - SetRatio(TopGrid.ColumnDefinitions[0], TopGrid.ColumnDefinitions[2], vm.SplitTopList); - SetRatio(BottomGrid.ColumnDefinitions[0], BottomGrid.ColumnDefinitions[2], vm.SplitBottomList); - - OuterGrid.RowDefinitions[0].Height = new GridLength(vm.SplitVertical, GridUnitType.Star); - OuterGrid.RowDefinitions[2].Height = new GridLength(1 - vm.SplitVertical, GridUnitType.Star); - } - - private static void SetRatio(ColumnDefinition first, ColumnDefinition second, double ratio) - { - first.Width = new GridLength(ratio, GridUnitType.Star); - second.Width = new GridLength(1 - ratio, GridUnitType.Star); - } - - private void SaveSplits() - { - if (_viewModel is null) return; - - _viewModel.SaveSplits( - RowRatio(OuterGrid.RowDefinitions[0], OuterGrid.RowDefinitions[2]), - ColumnRatio(TopGrid.ColumnDefinitions[0], TopGrid.ColumnDefinitions[2]), - ColumnRatio(BottomGrid.ColumnDefinitions[0], BottomGrid.ColumnDefinitions[2])); - } - - /// - /// Das Verhaeltnis wird aus den tatsaechlichen Pixelbreiten gebildet, nicht aus den - /// Sternwerten: Der GridSplitter setzt beim Ziehen mitunter absolute Breiten, und - /// dann stuenden in den Sternwerten noch die Zahlen von vor dem Zug. - /// - private static double ColumnRatio(ColumnDefinition first, ColumnDefinition second) - => Ratio(first.ActualWidth, second.ActualWidth); - - private static double RowRatio(RowDefinition first, RowDefinition second) - => Ratio(first.ActualHeight, second.ActualHeight); - - private static double Ratio(double first, double second) - { - var total = first + second; - return total > 0 ? first / total : 0.5; - } - - private async Task OnRequestAddAgentDialog(AddAgentViewModel vm) - { - if (TopLevel.GetTopLevel(this) is not Window window) return null; - - var dialog = new AddAgentWindow { DataContext = vm }; - await dialog.ShowDialog(window); - return vm.Result; - } - - private async Task OnRequestTextEditorDialog(string title, string text) - { - if (TopLevel.GetTopLevel(this) is not Window window) return null; - - return await TextEditorWindow.ShowAsync(window, title, text); - } -} diff --git a/src/ClawdDotNet.Desktop/Views/BackupPageView.axaml b/src/ClawdDotNet.Desktop/Views/BackupPageView.axaml deleted file mode 100644 index 4ded51f..0000000 --- a/src/ClawdDotNet.Desktop/Views/BackupPageView.axaml +++ /dev/null @@ -1,156 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/ClawdDotNet.Desktop/Views/InfoPageView.axaml.cs b/src/ClawdDotNet.Desktop/Views/InfoPageView.axaml.cs deleted file mode 100644 index 21db0ba..0000000 --- a/src/ClawdDotNet.Desktop/Views/InfoPageView.axaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Avalonia.Controls; - -namespace ClawdDotNet.Desktop.Views; - -public partial class InfoPageView : UserControl -{ - public InfoPageView() - { - InitializeComponent(); - } -} diff --git a/src/ClawdDotNet.Desktop/Views/InstancePickerWindow.axaml b/src/ClawdDotNet.Desktop/Views/InstancePickerWindow.axaml deleted file mode 100644 index 5768ab3..0000000 --- a/src/ClawdDotNet.Desktop/Views/InstancePickerWindow.axaml +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/ClawdDotNet.Desktop/Views/LogPageView.axaml.cs b/src/ClawdDotNet.Desktop/Views/LogPageView.axaml.cs deleted file mode 100644 index bbf7971..0000000 --- a/src/ClawdDotNet.Desktop/Views/LogPageView.axaml.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Avalonia.Controls; -using ClawdDotNet.Desktop.ViewModels; - -namespace ClawdDotNet.Desktop.Views; - -public partial class LogPageView : UserControl -{ - public LogPageView() - { - InitializeComponent(); - - // Mitlaufen: Nach jeder neuen Zeile ans Ende springen — aber nur, solange der - // Haken gesetzt ist. Das gehoert in die Ansicht, weil nur sie den ScrollViewer - // kennt; das Ansichtsmodell haelt lediglich den Schalter. - Scroller.ScrollChanged += (_, _) => - { - if (DataContext is LogPageViewModel { FollowTail: true }) - Scroller.ScrollToEnd(); - }; - } -} diff --git a/src/ClawdDotNet.Desktop/Views/MainWindow.axaml b/src/ClawdDotNet.Desktop/Views/MainWindow.axaml deleted file mode 100644 index 8ed1080..0000000 --- a/src/ClawdDotNet.Desktop/Views/MainWindow.axaml +++ /dev/null @@ -1,231 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/ClawdDotNet.Desktop/Views/MainWindow.axaml.cs b/src/ClawdDotNet.Desktop/Views/MainWindow.axaml.cs deleted file mode 100644 index a1c654c..0000000 --- a/src/ClawdDotNet.Desktop/Views/MainWindow.axaml.cs +++ /dev/null @@ -1,168 +0,0 @@ -using Avalonia; -using Avalonia.Controls; -using Avalonia.Threading; -using ClawdDotNet.Desktop.ViewModels; - -namespace ClawdDotNet.Desktop.Views; - -public partial class MainWindow : Window -{ - private bool _confirmedClose; - - public MainWindow() - { - InitializeComponent(); - Closing += OnClosing; - } - - /// - /// Schließt ohne Rückfrage — für eine Beendigung, die nicht von diesem Fenster ausgeht. - /// - /// Warum das nötig ist. Der Bestätigungsdialog schützt vor dem - /// versehentlichen Klick eines Menschen. Bittet dagegen der Instanzmanager über den - /// Socket, steht niemand davor: Der Dialog bliebe offen, die zehn Sekunden liefen ab, - /// und niemand klickte. Der Manager wartete seine Frist ab und schösse den Prozess - /// dann ab — der Dialog, der ein hartes Ende verhindern soll, hätte es garantiert. - /// - public void BeendenOhneRueckfrage() - { - _confirmedClose = true; - Close(); - } - - private async void OnClosing(object? sender, WindowClosingEventArgs e) - { - if (_confirmedClose) return; - - // Schließen zunächst abbrechen, um Bestätigungsdialog anzuzeigen - e.Cancel = true; - - var confirmed = await ShowExitConfirmationAsync(this); - if (confirmed) - { - _confirmedClose = true; - Close(); - } - } - - protected override void OnDataContextChanged(EventArgs e) - { - base.OnDataContextChanged(e); - - // Der Instanzwechsel haengt nicht mehr hier, sondern in App: Er braucht den - // Aufbau und die Lebensdauer der Anwendung, und beides kennt das Fenster nicht. - // Vorher wurde hier ein InstancePickerWindow ganz ohne DataContext geoeffnet — - // ein leerer Dialog, dessen Auswahl niemand ausgewertet hat. - if (DataContext is MainWindowViewModel vm) - vm.RequestExit += Close; - } - - internal static async Task ShowExitConfirmationAsync(Window? owner) - { - var completion = new TaskCompletionSource(); - var remainingSeconds = 10; - - var cancelBtn = new Button - { - Content = "Abbrechen (Instanz läuft weiter)", - IsCancel = true - }; - - var exitBtn = new Button - { - Content = $"Instanz beenden ({remainingSeconds}s)", - IsEnabled = false - }; - exitBtn.Classes.Add("danger"); - - var countdownText = new TextBlock - { - Text = $"Bestätigung gesperrt: Noch {remainingSeconds} Sekunden…", - Classes = { "caption" } - }; - - var timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) }; - timer.Tick += (_, _) => - { - remainingSeconds--; - if (remainingSeconds > 0) - { - countdownText.Text = $"Bestätigung gesperrt: Noch {remainingSeconds} Sekunden…"; - exitBtn.Content = $"Instanz beenden ({remainingSeconds}s)"; - } - else - { - timer.Stop(); - exitBtn.IsEnabled = true; - exitBtn.Content = "Instanz jetzt endgültig beenden"; - countdownText.Text = "Sperre aufgehoben — Bestätigung jetzt möglich."; - } - }; - - var window = new Window - { - Title = "ClawdDotNet – Instanz beenden", - Width = 500, - SizeToContent = SizeToContent.Height, - CanResize = false, - WindowStartupLocation = WindowStartupLocation.CenterScreen, - Icon = owner?.Icon, - Content = new StackPanel - { - Margin = new Thickness(20), - Spacing = 16, - Children = - { - new TextBlock - { - Text = "Achtung: Produktivinstanz beenden", - Classes = { "h1" } - }, - new TextBlock - { - Text = "ClawdDotNet-Instanzen sind auf dauerhaften Dauerbetrieb ausgelegt. " - + "Das Beenden stoppt alle aktiven Agenten, Automationen, Web-Zugriffe und Hintergrundaufgaben dieser Instanz geordnet.", - TextWrapping = Avalonia.Media.TextWrapping.Wrap - }, - countdownText, - new StackPanel - { - Orientation = Avalonia.Layout.Orientation.Horizontal, - Spacing = 10, - HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Right, - Children = { cancelBtn, exitBtn } - } - } - } - }; - - cancelBtn.Click += (_, _) => - { - timer.Stop(); - completion.TrySetResult(false); - window.Close(); - }; - - exitBtn.Click += (_, _) => - { - timer.Stop(); - completion.TrySetResult(true); - window.Close(); - }; - - window.Closed += (_, _) => - { - timer.Stop(); - completion.TrySetResult(false); - }; - - timer.Start(); - - if (owner is not null) - await window.ShowDialog(owner); - else - window.Show(); - - return await completion.Task; - } -} diff --git a/src/ClawdDotNet.Desktop/Views/RestoreBackupWindow.axaml b/src/ClawdDotNet.Desktop/Views/RestoreBackupWindow.axaml deleted file mode 100644 index 4a22dfb..0000000 --- a/src/ClawdDotNet.Desktop/Views/RestoreBackupWindow.axaml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/ClawdDotNet.Desktop/Views/SettingsPageView.axaml.cs b/src/ClawdDotNet.Desktop/Views/SettingsPageView.axaml.cs deleted file mode 100644 index 790d578..0000000 --- a/src/ClawdDotNet.Desktop/Views/SettingsPageView.axaml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Avalonia.Controls; - -namespace ClawdDotNet.Desktop.Views; - -public partial class SettingsPageView : UserControl -{ - public SettingsPageView() - { - InitializeComponent(); - } -} diff --git a/src/ClawdDotNet.Desktop/Views/TasksPageView.axaml b/src/ClawdDotNet.Desktop/Views/TasksPageView.axaml deleted file mode 100644 index 9ae3046..0000000 --- a/src/ClawdDotNet.Desktop/Views/TasksPageView.axaml +++ /dev/null @@ -1,257 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/ClawdDotNet.Desktop/Views/TasksPageView.axaml.cs b/src/ClawdDotNet.Desktop/Views/TasksPageView.axaml.cs deleted file mode 100644 index fae5b62..0000000 --- a/src/ClawdDotNet.Desktop/Views/TasksPageView.axaml.cs +++ /dev/null @@ -1,46 +0,0 @@ -using Avalonia.Controls; -using ClawdDotNet.Desktop.ViewModels; - -namespace ClawdDotNet.Desktop.Views; - -public partial class TasksPageView : UserControl -{ - public TasksPageView() - { - InitializeComponent(); - } - - protected override void OnDataContextChanged(EventArgs e) - { - base.OnDataContextChanged(e); - if (DataContext is TasksPageViewModel vm) - { - vm.RequestAddJobDialog += OnRequestAddJobDialog; - vm.RequestAddServiceDialog += OnRequestAddServiceDialog; - } - } - - private async Task OnRequestAddJobDialog(AddJobViewModel vm) - { - var topLevel = TopLevel.GetTopLevel(this); - if (topLevel is Window window) - { - var dialog = new AddJobWindow { DataContext = vm }; - await dialog.ShowDialog(window); - return vm.Result; - } - return null; - } - - private async Task OnRequestAddServiceDialog(AddServiceViewModel vm) - { - var topLevel = TopLevel.GetTopLevel(this); - if (topLevel is Window window) - { - var dialog = new AddServiceWindow { DataContext = vm }; - await dialog.ShowDialog(window); - return vm.Result; - } - return null; - } -} diff --git a/src/ClawdDotNet.Desktop/Views/TextEditorWindow.axaml b/src/ClawdDotNet.Desktop/Views/TextEditorWindow.axaml deleted file mode 100644 index c97b157..0000000 --- a/src/ClawdDotNet.Desktop/Views/TextEditorWindow.axaml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/ClawdDotNet.Desktop/Views/TokenUsagePageView.axaml.cs b/src/ClawdDotNet.Desktop/Views/TokenUsagePageView.axaml.cs deleted file mode 100644 index d3d57b3..0000000 --- a/src/ClawdDotNet.Desktop/Views/TokenUsagePageView.axaml.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Avalonia.Controls; - -namespace ClawdDotNet.Desktop.Views; - -public partial class TokenUsagePageView : UserControl -{ - public TokenUsagePageView() => InitializeComponent(); -} diff --git a/src/ClawdDotNet.Desktop/Views/ToolSettingsView.axaml b/src/ClawdDotNet.Desktop/Views/ToolSettingsView.axaml deleted file mode 100644 index f05bd54..0000000 --- a/src/ClawdDotNet.Desktop/Views/ToolSettingsView.axaml +++ /dev/null @@ -1,239 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/ClawdDotNet.Desktop/Views/ToolSettingsView.axaml.cs b/src/ClawdDotNet.Desktop/Views/ToolSettingsView.axaml.cs deleted file mode 100644 index 99ec1b7..0000000 --- a/src/ClawdDotNet.Desktop/Views/ToolSettingsView.axaml.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Avalonia.Controls; - -namespace ClawdDotNet.Desktop.Views; - -public partial class ToolSettingsView : UserControl -{ - public ToolSettingsView() => InitializeComponent(); -} diff --git a/src/ClawdDotNet.Desktop/i18n/de.json b/src/ClawdDotNet.Desktop/i18n/de.json deleted file mode 100644 index ca9f13f..0000000 --- a/src/ClawdDotNet.Desktop/i18n/de.json +++ /dev/null @@ -1,341 +0,0 @@ -{ - "desktop.mainWindow.title": "ClawdDotNet", - "desktop.mainWindow.sidebarTooltip": "Seitenleiste ein-/ausklappen", - "desktop.mainWindow.switchInstance": "Instanz wechseln", - "desktop.mainWindow.instance": "INSTANZ", - "desktop.mainWindow.themeLight": "Hellmodus", - "desktop.mainWindow.themeDark": "Dunkelmodus", - "desktop.mainWindow.themeToggle": "Farbschema umschalten", - "desktop.mainWindow.openInstanceFolder": "Instanz-Ordner öffnen", - "desktop.mainWindow.instanceManager": "Instanzmanager", - "desktop.mainWindow.exit": "Beenden", - "desktop.mainWindow.instanceLabel": "Instanz: {0}", - "desktop.mainWindow.apiStatus": "API {0}", - "desktop.mainWindow.credits": "Credits: ${0:F2} von ${1:F2}", - "desktop.mainWindow.creditsNone": "Credits: —", - "desktop.mainWindow.dismiss": "Ausblenden", - - "desktop.nav.work": "Arbeiten", - "desktop.nav.analytics": "Analyse", - "desktop.nav.system": "System", - - "desktop.status.unknown": "unbekannt", - "desktop.status.design": "Entwurf", - "desktop.status.noApiKey": "kein API-Key", - "desktop.status.noUsageData": "keine Nutzungsdaten", - "desktop.status.ready": "Bereit", - "desktop.status.reachable": "OK", - "desktop.status.unreachable": "nicht erreichbar", - - "desktop.chat.agent": "Agent:", - "desktop.chat.clearHistory": "Verlauf leeren", - "desktop.chat.abort": "Abbrechen", - "desktop.chat.inputPlaceholder": "Nachricht eingeben… (Enter zum Senden, Shift+Enter für neue Zeile)", - "desktop.chat.send": "Senden", - "desktop.chat.statusReady": "Bereit", - "desktop.chat.statusSending": "Sende…", - "desktop.chat.statusDesign": "Entwurfsmodus", - "desktop.chat.noApiKey": "OpenRouter API-Key ist nicht konfiguriert. Bitte in den Einstellungen hinterlegen.", - "desktop.chat.noAgent": "Bitte einen Agenten auswählen.", - "desktop.chat.emptyMessage": "Bitte eine Nachricht eingeben.", - - "desktop.agents.addAgent": "Agent", - "desktop.agents.removeAgent": "Agent", - "desktop.agents.runNow": "Jetzt ausf.", - "desktop.agents.identity": "Identity", - "desktop.agents.soul": "Soul", - "desktop.agents.folder": "Ordner", - "desktop.agents.save": "Speichern", - "desktop.agents.thDisplayName": "ANZEIGENAME", - "desktop.agents.thModel": "MODELL", - "desktop.agents.thSummary": "KURZINFO", - "desktop.agents.kickerGeneralModel": "ALLGEMEIN & MODELL", - "desktop.agents.agentId": "Agent-ID", - "desktop.agents.displayName": "Anzeigename", - "desktop.agents.model": "Modell", - "desktop.agents.promptCaching": "Prompt Caching", - "desktop.agents.roleDescription": "Rolle / Beschreibung", - "desktop.agents.systemPrompt": "System-Prompt (zusätzliche Anweisungen)", - "desktop.agents.kickerLimits": "GRENZEN", - "desktop.agents.limitsTitle": "Schutzgrenzen (LoopGuard & Budget)", - "desktop.agents.maxSteps": "Max. Schritte pro Run", - "desktop.agents.timeoutSeconds": "Timeout (Sekunden)", - "desktop.agents.maxContextTokens": "Max. Kontext-Tokens", - "desktop.agents.maxToolResultChars": "Max. Tool-Ergebnis (Zeichen)", - "desktop.agents.dailyCost": "Tagesbudget ($ USD)", - "desktop.agents.dailyTokens": "Tagesbudget (Tokens)", - "desktop.agents.whenExhausted": "Wenn das Budget erschöpft ist (wiederkehrende Aufgaben)", - "desktop.agents.whenExhaustedHint": "expire: Der verpasste Lauf verfällt und wird an der Aufgabe vermerkt. catchUpOnce: Alle verpassten Läufe werden am nächsten Tag durch einen Lauf nachgeholt, nach der regulären Arbeit des Tages. Einmalige Aufgaben werden immer auf den nächsten Tag mitgenommen.", - "desktop.agents.allowedToolsFor": "ZUGELASSENE WERKZEUGE FÜR {0}", - "desktop.agents.thTool": "WERKZEUG", - "desktop.agents.thDescription": "BESCHREIBUNG", - "desktop.agents.toolSettingsKicker": "WERKZEUG-EINSTELLUNGEN", - "desktop.agents.apply": "Übernehmen", - "desktop.agents.saved": "Agenten erfolgreich gespeichert.", - - "desktop.tasks.tabJobs": "Geplante Jobs", - "desktop.tasks.tabServices": "Dienste", - "desktop.tasks.tabHistory": "Verlauf", - "desktop.tasks.addJob": "Job hinzufügen", - "desktop.tasks.editJob": "Bearbeiten", - "desktop.tasks.removeJob": "Entfernen", - "desktop.tasks.toggleJob": "Aktivieren/Deaktivieren", - "desktop.tasks.runJobNow": "Jetzt ausführen", - "desktop.tasks.refresh": "Aktualisieren", - "desktop.tasks.thType": "TYP", - "desktop.tasks.thAgent": "AGENT", - "desktop.tasks.thTask": "TOOL / NACHRICHT", - "desktop.tasks.thCron": "CRON", - "desktop.tasks.thNextRun": "NÄCHSTER LAUF", - "desktop.tasks.thLastRun": "LETZTER LAUF", - "desktop.tasks.thStatus": "STATUS", - - "desktop.services.addService": "Dienst hinzufügen", - "desktop.services.removeService": "Entfernen", - "desktop.services.toggleService": "Aktivieren/Deaktivieren", - "desktop.services.thName": "DIENSTNAME", - "desktop.services.thType": "TYP", - "desktop.services.thPort": "PORT", - "desktop.services.thStatus": "STATUS", - "desktop.services.thDescription": "BESCHREIBUNG", - - "desktop.history.refresh": "Verlauf aktualisieren", - "desktop.history.thTime": "ZEITPUNKT", - "desktop.history.thJob": "JOB", - "desktop.history.thAgent": "AGENT", - "desktop.history.thDescription": "BESCHREIBUNG", - "desktop.history.thStatus": "STATUS", - "desktop.history.thDetails": "DETAILS", - - "desktop.usage.kickerTokens7d": "TOKENS (7 TAGE)", - "desktop.usage.kickerCost7d": "KOSTEN (7 TAGE)", - "desktop.usage.kickerRuns7d": "RUNS (7 TAGE)", - "desktop.usage.refresh": "Aktualisieren", - "desktop.usage.tokensPerDay": "Tokens pro Tag", - "desktop.usage.breakdownTitle": "Aufschlüsselung nach Agent & Modell", - "desktop.usage.thAgent": "AGENT", - "desktop.usage.thModel": "MODELL", - "desktop.usage.thTokens": "TOKENS", - "desktop.usage.thCost": "KOSTEN", - "desktop.usage.thRuns": "RUNS", - "desktop.usage.empty": "Noch keine Tokennutzung aufgezeichnet.", - - "desktop.agentChats.agentA": "Agent A:", - "desktop.agentChats.agentB": "Agent B:", - "desktop.agentChats.empty": "Noch keine Nachrichten zwischen diesen Agenten aufgezeichnet.", - "desktop.agentChats.needTwo": "Für einen Verlauf braucht es mindestens zwei Agenten in dieser Instanz.", - - "desktop.backup.kickerManual": "MANUELL", - "desktop.backup.titleCreate": "Sicherung erstellen", - "desktop.backup.targetFolder": "Zielordner", - "desktop.backup.targetFolderPlaceholder": "Zielordner für Sicherungen…", - "desktop.backup.browse": "Durchsuchen…", - "desktop.backup.credentials": "Zugangsdaten", - "desktop.backup.credentialsExclude": "nicht mitsichern", - "desktop.backup.credentialsProtect": "mit Passphrase schützen", - "desktop.backup.passphrase": "Passphrase eingeben", - "desktop.backup.passphraseRepeat": "Passphrase wiederholen", - "desktop.backup.scope": "Umfang", - "desktop.backup.scopeChat": "Chatverläufe", - "desktop.backup.scopeLogs": "Protokolle", - "desktop.backup.createNow": "Sicherung jetzt erstellen", - "desktop.backup.kickerAuto": "AUTOMATIK", - "desktop.backup.titleAuto": "Automatische Sicherung", - "desktop.backup.autoDaily": "täglich sichern um", - "desktop.backup.time": "Uhrzeit", - "desktop.backup.keep": "Aufbewahren", - "desktop.backup.autoHint": "Die Automatik sichert ohne Zugangsdaten — eine gespeicherte Passphrase wäre wirkungslos.", - "desktop.backup.kickerExisting": "BESTAND", - "desktop.backup.titleExisting": "Vorhandene Sicherungen", - "desktop.backup.refresh": "Aktualisieren", - "desktop.backup.openFolder": "Ordner öffnen", - "desktop.backup.delete": "Löschen", - "desktop.backup.restore": "Wiederherstellen…", - "desktop.backup.thFilename": "DATEINAME", - "desktop.backup.thCreatedAt": "ERSTELLT AM", - "desktop.backup.thInstance": "INSTANZ", - "desktop.backup.thSize": "GRÖSSE", - "desktop.backup.thSecrets": "ZUGANGSDATEN", - - "desktop.logs.module": "Modul:", - "desktop.logs.level": "Stufe:", - "desktop.logs.refresh": "Aktualisieren", - "desktop.logs.clear": "Leeren", - "desktop.logs.openFolder": "Ordner öffnen", - "desktop.logs.follow": "Mitlaufen", - - "desktop.settings.discard": "Verwerfen", - "desktop.settings.save": "Speichern", - "desktop.settings.instance": "INSTANZ", - "desktop.settings.instanceName": "Instanz-Name", - "desktop.settings.apiKey": "OpenRouter API-Key", - "desktop.settings.autostart": "Autostart durch Manager", - "desktop.settings.autostartHint": "Der Instanzmanager startet diese Instanz, wenn er hochkommt, und wieder, wenn sie abstürzt. Nach mehreren Neustarts in kurzer Folge setzt er aus und meldet es.", - "desktop.settings.logDir": "Protokoll-Verzeichnis", - "desktop.settings.logDirHint": "Gilt nur für diese Instanz. Leer heißt: Unterordner Logs im Instanzverzeichnis.", - "desktop.settings.dailyCost": "Tagesbudget ($ USD)", - "desktop.settings.dailyTokens": "Tagesbudget (Tokens)", - "desktop.settings.general": "ALLGEMEIN", - "desktop.settings.instancesDir": "Instanzen-Verzeichnis", - "desktop.settings.minLogLevel": "Minimaler Log-Level", - "desktop.settings.openRouterUrl": "OpenRouter Base-URL", - "desktop.settings.language": "Sprache", - "desktop.settings.dcAndLicense": "DEPLOYMENTCENTER & LIZENZ", - "desktop.settings.dcUrl": "Server-URL", - "desktop.settings.dcToken": "Master-Token", - "desktop.settings.dcEnv": "Umgebung", - "desktop.settings.updateChannel": "Update-Kanal", - "desktop.settings.licenseKey": "Lizenzschlüssel", - "desktop.settings.errorReporting": "Fehler automatisch an Deploymentcenter melden", - "desktop.settings.updateCheck": "Beim Start automatisch auf Updates prüfen", - "desktop.settings.saved": "Einstellungen und Instanz-Konfiguration gespeichert.", - "desktop.settings.savedLogRestart": "Gespeichert. Das Protokoll-Verzeichnis gilt ab dem nächsten Start.", - - "desktop.info.kickerApp": "ANWENDUNG", - "desktop.info.build": "Build", - "desktop.info.version": "Version", - "desktop.info.buildSummary": "Build-Zusammenfassung", - "desktop.info.kickerInstance": "INSTANZ", - "desktop.info.currentInstance": "Aktuelle Instanz", - "desktop.info.openFolder": "Instanz-Ordner öffnen", - "desktop.info.name": "Name", - "desktop.info.id": "ID", - "desktop.info.path": "Pfad", - "desktop.info.logDir": "Log-Ordner", - "desktop.info.openRouter": "OpenRouter", - "desktop.info.kickerModules": "MODULE", - "desktop.info.assemblies": "Baugruppen", - "desktop.info.thModule": "MODUL", - "desktop.info.thBuild": "BUILD", - "desktop.info.thBuildDate": "BUILD-DATUM", - "desktop.info.thChanges": "ÄNDERUNGEN", - - "desktop.dialog.addAgent": "Neuen Agenten anlegen", - "desktop.dialog.agentId": "Agent-ID (eindeutiger Schlüssel):", - "desktop.dialog.agentDisplayName": "Anzeigename:", - "desktop.dialog.defaultModel": "Standard-Modell:", - "desktop.dialog.roleDescription": "Beschreibung / Rolle:", - "desktop.dialog.addJobTitle": "Job hinzufügen / bearbeiten", - "desktop.dialog.jobType": "Job-Typ:", - "desktop.dialog.agentWakeup": "Agent Wakeup (Periodische Ausführung)", - "desktop.dialog.toolJob": "Tool Job (Werkzeug-spezifischer Job)", - "desktop.dialog.jobTypeId": "Job-Typ-ID / Name:", - "desktop.dialog.taskMessage": "Aufgabenbeschreibung / Nachricht:", - "desktop.dialog.cronExpression": "Cron-Ausdruck:", - "desktop.dialog.cronHint": "Syntax: Min Std Tag Mon Wochentag (z.B. '*/15 * * * *' alle 15 Minuten)", - "desktop.dialog.runOnStart": "Beim Anwendungsstart einmalig sofort ausführen", - "desktop.dialog.addServiceTitle": "Dienst (Service) hinzufügen", - "desktop.dialog.serviceName": "Name des Dienstes:", - "desktop.dialog.serviceType": "Typ:", - "desktop.dialog.servicePort": "Port:", - "desktop.dialog.serviceDesc": "Beschreibung:", - "desktop.dialog.restoreTitle": "Sicherung wiederherstellen", - "desktop.dialog.backupInfo": "Sicherungsinformationen", - "desktop.dialog.backupInstance": "Instanz: {0}", - "desktop.dialog.backupCreated": "Erstellt: {0:g}", - "desktop.dialog.backupFiles": "Dateien: {0}", - "desktop.dialog.backupSecrets": "Zugangsdaten: {0}", - "desktop.dialog.targetDir": "Zielordner:", - "desktop.dialog.chooseFolder": "Ordner wählen", - "desktop.dialog.restoreHint": "Hinweis: Es wird empfohlen, in einen neuen Ordner wiederherzustellen, um Konflikte mit laufenden Prozessen zu vermeiden.", - "desktop.dialog.passphrase": "Passphrase:", - "desktop.dialog.passphraseProtected": "Diese Sicherung enthält geschützte Zugangsdaten.", - "desktop.dialog.overwriteExisting": "Vorhandene Dateien im Zielordner überschreiben", - "desktop.dialog.licenseTitle": "ClawdDotNet – Lizenz", - "desktop.dialog.licenseKey": "Lizenzschlüssel", - "desktop.dialog.hardwareId": "Hardware-ID (für den Support):", - "desktop.dialog.verify": "Prüfen", - "desktop.dialog.textEditorTitle": "Text bearbeiten", - - "desktop.instancePicker.titleSwitch": "Instanz wechseln", - "desktop.instancePicker.titleSelect": "Instanz wählen", - "desktop.instancePicker.hintSwitch": "Jede Instanz läuft unabhängig mit eigenen Agenten und Daten. Wechseln startet ClawdDotNet mit der gewählten Instanz neu.", - "desktop.instancePicker.hintSelect": "Jede Instanz läuft unabhängig mit eigenen Agenten und Daten.", - "desktop.instancePicker.confirmSwitch": "Wechseln", - "desktop.instancePicker.confirmStart": "Starten", - "desktop.instancePicker.newInstancePlaceholder": "Name der neuen Instanz", - "desktop.instancePicker.create": "Anlegen", - "desktop.instancePicker.active": "Aktiv", - "desktop.instancePicker.dirLabel": "Verzeichnis: {0}", - "desktop.instancePicker.agentsCount": "{0} Agenten · API-Key {1}", - "desktop.instancePicker.apiKeyConfigured": "konfiguriert", - "desktop.instancePicker.apiKeyMissing": "fehlt", - "desktop.instancePicker.tooltipConfigured": "API-Key hinterlegt", - "desktop.instancePicker.tooltipMissing": "Kein API-Key — Agenten bleiben deaktiviert", - "desktop.instancePicker.nameRequired": "Bitte einen Instanznamen eingeben.", - "desktop.instancePicker.createFailed": "Instanz konnte nicht angelegt werden: {0}", - - "desktop.startMode.title": "ClawdDotNet – Startmodus wählen", - "desktop.startMode.question": "Wie möchtest du ClawdDotNet starten?", - "desktop.startMode.managerBtn": "Instanzmanager starten (Empfohlen)", - "desktop.startMode.standaloneBtn": "Als Standalone-Instanz starten", - "desktop.startMode.explanation": "• Instanzmanager (Empfohlen):\n Startet den zentralen Hintergrund-Manager und öffnet die Verwaltung im Browser. Ermöglicht den stabilen Dauerbetrieb mehrerer Instanzen parallel ohne Absturzrisiko.\n\n• Standalone-Modus:\n Startet genau eine Instanz direkt als einzelnes Desktop-Fenster.", - - "desktop.standaloneSwitch.title": "ClawdDotNet – Instanzwechsel (Standalone)", - "desktop.standaloneSwitch.warning": "Achtung: Standalone-Modus", - "desktop.standaloneSwitch.text": "Diese Instanz läuft eigenständig ohne Instanzmanager.\n\nWenn du die Instanz hier wechselst, wird diese Instanz vollständig beendet und alle laufenden Agenten und Hintergrunddienste werden gestoppt.\n\nEmpfehlung: Starte stattdessen den Instanzmanager, um mehrere Instanzen gleichzeitig und unabhängig voneinander zu betreiben.", - "desktop.standaloneSwitch.switchAnyway": "Instanz trotzdem wechseln", - - "desktop.toolSettings.noSettings": "Dieses Werkzeug benötigt keine weiteren Einstellungen.", - "desktop.toolSettings.host": "Host", - "desktop.toolSettings.port": "Port", - "desktop.toolSettings.username": "Benutzername", - "desktop.toolSettings.password": "Passwort", - "desktop.toolSettings.rootPath": "Root-Pfad", - "desktop.toolSettings.imapHost": "IMAP-Host", - "desktop.toolSettings.imapPort": "IMAP-Port", - "desktop.toolSettings.smtpHost": "SMTP-Host", - "desktop.toolSettings.smtpPort": "SMTP-Port", - "desktop.toolSettings.allowedRecipients": "Erlaubte Empfänger", - "desktop.toolSettings.type": "Typ", - "desktop.toolSettings.connectionString": "Connection-String", - "desktop.toolSettings.accessLevel": "Zugriffsebene", - "desktop.toolSettings.allowedTables": "Erlaubte Tabellen", - "desktop.toolSettings.botToken": "Bot-Token", - "desktop.toolSettings.defaultChatId": "Standard Chat-ID", - "desktop.toolSettings.allowedChatIds": "Erlaubte Chat-IDs", - "desktop.toolSettings.defaultProvider": "Standard-Provider", - "desktop.toolSettings.cacheTtl": "Cache TTL (Sekunden)", - "desktop.toolSettings.twelveDataKey": "Twelve Data Key", - "desktop.toolSettings.alphaVantageKey": "Alpha Vantage Key", - "desktop.toolSettings.allowedDomains": "Erlaubte Domains", - "desktop.toolSettings.maxResponseKb": "Max. Antwortgröße (KB)", - "desktop.toolSettings.userAgent": "User Agent", - "desktop.toolSettings.xApiKey": "X (Twitter) API-Key", - "desktop.toolSettings.xAccounts": "X Accounts", - "desktop.toolSettings.subreddits": "Subreddits", - "desktop.toolSettings.redditPostLimit": "Reddit Post Limit", - "desktop.toolSettings.openRouterKey": "OpenRouter Key", - "desktop.toolSettings.sttModel": "STT-Modell", - "desktop.toolSettings.youtubeChannels": "YouTube-Kanäle", - "desktop.toolSettings.fileRwPersonalExt": "Erlaubte Dateiendungen (persönlich)", - "desktop.toolSettings.fileRwSharedAccess": "Zugriffsebene (geteilt)", - "desktop.toolSettings.fileRwSharedExt": "Erlaubte Dateiendungen (geteilt)", - "desktop.toolSettings.fileRwProtectedPaths": "Geschützte Pfade", - - "nav.chat": "Chat", - "nav.agents": "Agenten", - "nav.tasks": "Aufgaben", - "nav.usage": "Tokennutzung", - "nav.agentChats": "Agenten-Chats", - "nav.backup": "Sicherung", - "nav.logs": "Protokoll", - "nav.settings": "Einstellungen", - "nav.info": "Info", - - "common.all": "Alle", - "common.save": "Speichern", - "common.cancel": "Abbrechen", - "common.delete": "Löschen", - "common.edit": "Bearbeiten", - "common.refresh": "Aktualisieren", - "common.close": "Schließen", - "common.discard": "Verwerfen", - "common.ready": "Bereit", - "common.loading": "Lade…", - "common.create": "Anlegen", - "common.add": "Hinzufügen", - "common.apply": "Übernehmen", - "common.ok": "OK", - "common.exit": "Beenden" -} diff --git a/src/ClawdDotNet.Desktop/i18n/en.json b/src/ClawdDotNet.Desktop/i18n/en.json deleted file mode 100644 index 6590e4f..0000000 --- a/src/ClawdDotNet.Desktop/i18n/en.json +++ /dev/null @@ -1,341 +0,0 @@ -{ - "desktop.mainWindow.title": "ClawdDotNet", - "desktop.mainWindow.sidebarTooltip": "Toggle sidebar", - "desktop.mainWindow.switchInstance": "Switch instance", - "desktop.mainWindow.instance": "INSTANCE", - "desktop.mainWindow.themeLight": "Light Mode", - "desktop.mainWindow.themeDark": "Dark Mode", - "desktop.mainWindow.themeToggle": "Toggle theme", - "desktop.mainWindow.openInstanceFolder": "Open Instance Folder", - "desktop.mainWindow.instanceManager": "Instance Manager", - "desktop.mainWindow.exit": "Exit", - "desktop.mainWindow.instanceLabel": "Instance: {0}", - "desktop.mainWindow.apiStatus": "API {0}", - "desktop.mainWindow.credits": "Credits: ${0:F2} of ${1:F2}", - "desktop.mainWindow.creditsNone": "Credits: —", - "desktop.mainWindow.dismiss": "Dismiss", - - "desktop.nav.work": "Work", - "desktop.nav.analytics": "Analytics", - "desktop.nav.system": "System", - - "desktop.status.unknown": "unknown", - "desktop.status.design": "Design", - "desktop.status.noApiKey": "no API key", - "desktop.status.noUsageData": "no usage data", - "desktop.status.ready": "Ready", - "desktop.status.reachable": "OK", - "desktop.status.unreachable": "unreachable", - - "desktop.chat.agent": "Agent:", - "desktop.chat.clearHistory": "Clear History", - "desktop.chat.abort": "Abort", - "desktop.chat.inputPlaceholder": "Type message… (Enter to send, Shift+Enter for new line)", - "desktop.chat.send": "Send", - "desktop.chat.statusReady": "Ready", - "desktop.chat.statusSending": "Sending…", - "desktop.chat.statusDesign": "Design Mode", - "desktop.chat.noApiKey": "OpenRouter API key is not configured. Please enter the key in Settings.", - "desktop.chat.noAgent": "Please select an agent.", - "desktop.chat.emptyMessage": "Please enter a message.", - - "desktop.agents.addAgent": "Agent", - "desktop.agents.removeAgent": "Agent", - "desktop.agents.runNow": "Run Now", - "desktop.agents.identity": "Identity", - "desktop.agents.soul": "Soul", - "desktop.agents.folder": "Folder", - "desktop.agents.save": "Save", - "desktop.agents.thDisplayName": "DISPLAY NAME", - "desktop.agents.thModel": "MODEL", - "desktop.agents.thSummary": "SUMMARY", - "desktop.agents.kickerGeneralModel": "GENERAL & MODEL", - "desktop.agents.agentId": "Agent ID", - "desktop.agents.displayName": "Display Name", - "desktop.agents.model": "Model", - "desktop.agents.promptCaching": "Prompt Caching", - "desktop.agents.roleDescription": "Role / Description", - "desktop.agents.systemPrompt": "System Prompt (additional instructions)", - "desktop.agents.kickerLimits": "LIMITS", - "desktop.agents.limitsTitle": "Guardrails (LoopGuard & Budget)", - "desktop.agents.maxSteps": "Max Steps per Run", - "desktop.agents.timeoutSeconds": "Timeout (seconds)", - "desktop.agents.maxContextTokens": "Max Context Tokens", - "desktop.agents.maxToolResultChars": "Max Tool Result (chars)", - "desktop.agents.dailyCost": "Daily Budget ($ USD)", - "desktop.agents.dailyTokens": "Daily Budget (Tokens)", - "desktop.agents.whenExhausted": "When the budget is exhausted (recurring tasks)", - "desktop.agents.whenExhaustedHint": "expire: the missed run lapses and is recorded on the task. catchUpOnce: all missed runs are caught up by one run the next day, after the day's regular work. One-time tasks are always carried over to the next day.", - "desktop.agents.allowedToolsFor": "ALLOWED TOOLS FOR {0}", - "desktop.agents.thTool": "TOOL", - "desktop.agents.thDescription": "DESCRIPTION", - "desktop.agents.toolSettingsKicker": "TOOL SETTINGS", - "desktop.agents.apply": "Apply", - "desktop.agents.saved": "Agents saved successfully.", - - "desktop.tasks.tabJobs": "Scheduled Jobs", - "desktop.tasks.tabServices": "Services", - "desktop.tasks.tabHistory": "History", - "desktop.tasks.addJob": "Add Job", - "desktop.tasks.editJob": "Edit", - "desktop.tasks.removeJob": "Remove", - "desktop.tasks.toggleJob": "Enable/Disable", - "desktop.tasks.runJobNow": "Run Now", - "desktop.tasks.refresh": "Refresh", - "desktop.tasks.thType": "TYPE", - "desktop.tasks.thAgent": "AGENT", - "desktop.tasks.thTask": "TOOL / MESSAGE", - "desktop.tasks.thCron": "CRON", - "desktop.tasks.thNextRun": "NEXT RUN", - "desktop.tasks.thLastRun": "LAST RUN", - "desktop.tasks.thStatus": "STATUS", - - "desktop.services.addService": "Add Service", - "desktop.services.removeService": "Remove", - "desktop.services.toggleService": "Enable/Disable", - "desktop.services.thName": "SERVICE NAME", - "desktop.services.thType": "TYPE", - "desktop.services.thPort": "PORT", - "desktop.services.thStatus": "STATUS", - "desktop.services.thDescription": "DESCRIPTION", - - "desktop.history.refresh": "Refresh History", - "desktop.history.thTime": "TIMESTAMP", - "desktop.history.thJob": "JOB", - "desktop.history.thAgent": "AGENT", - "desktop.history.thDescription": "DESCRIPTION", - "desktop.history.thStatus": "STATUS", - "desktop.history.thDetails": "DETAILS", - - "desktop.usage.kickerTokens7d": "TOKENS (7 DAYS)", - "desktop.usage.kickerCost7d": "COST (7 DAYS)", - "desktop.usage.kickerRuns7d": "RUNS (7 DAYS)", - "desktop.usage.refresh": "Refresh", - "desktop.usage.tokensPerDay": "Tokens per Day", - "desktop.usage.breakdownTitle": "Breakdown by Agent & Model", - "desktop.usage.thAgent": "AGENT", - "desktop.usage.thModel": "MODEL", - "desktop.usage.thTokens": "TOKENS", - "desktop.usage.thCost": "COST", - "desktop.usage.thRuns": "RUNS", - "desktop.usage.empty": "No token usage recorded yet.", - - "desktop.agentChats.agentA": "Agent A:", - "desktop.agentChats.agentB": "Agent B:", - "desktop.agentChats.empty": "No messages between these agents yet.", - "desktop.agentChats.needTwo": "At least two agents are required in this instance to view a conversation history.", - - "desktop.backup.kickerManual": "MANUAL", - "desktop.backup.titleCreate": "Create Backup", - "desktop.backup.targetFolder": "Target Folder", - "desktop.backup.targetFolderPlaceholder": "Target folder for backups…", - "desktop.backup.browse": "Browse…", - "desktop.backup.credentials": "Credentials", - "desktop.backup.credentialsExclude": "do not include", - "desktop.backup.credentialsProtect": "protect with passphrase", - "desktop.backup.passphrase": "Enter passphrase", - "desktop.backup.passphraseRepeat": "Repeat passphrase", - "desktop.backup.scope": "Scope", - "desktop.backup.scopeChat": "Chat history", - "desktop.backup.scopeLogs": "Logs", - "desktop.backup.createNow": "Create Backup Now", - "desktop.backup.kickerAuto": "AUTOMATIC", - "desktop.backup.titleAuto": "Automatic Backup", - "desktop.backup.autoDaily": "daily backup at", - "desktop.backup.time": "Time", - "desktop.backup.keep": "Keep Count", - "desktop.backup.autoHint": "Automatic backup excludes credentials — a saved passphrase would be ineffective.", - "desktop.backup.kickerExisting": "EXISTING", - "desktop.backup.titleExisting": "Existing Backups", - "desktop.backup.refresh": "Refresh", - "desktop.backup.openFolder": "Open Folder", - "desktop.backup.delete": "Delete", - "desktop.backup.restore": "Restore…", - "desktop.backup.thFilename": "FILENAME", - "desktop.backup.thCreatedAt": "CREATED AT", - "desktop.backup.thInstance": "INSTANCE", - "desktop.backup.thSize": "SIZE", - "desktop.backup.thSecrets": "CREDENTIALS", - - "desktop.logs.module": "Module:", - "desktop.logs.level": "Level:", - "desktop.logs.refresh": "Refresh", - "desktop.logs.clear": "Clear", - "desktop.logs.openFolder": "Open Folder", - "desktop.logs.follow": "Follow Tail", - - "desktop.settings.discard": "Discard", - "desktop.settings.save": "Save", - "desktop.settings.instance": "INSTANCE", - "desktop.settings.instanceName": "Instance Name", - "desktop.settings.apiKey": "OpenRouter API Key", - "desktop.settings.autostart": "Autostart by Manager", - "desktop.settings.autostartHint": "The instance manager starts this instance on launch and restarts it if it crashes.", - "desktop.settings.logDir": "Log Directory", - "desktop.settings.logDirHint": "Applies only to this instance. Empty means: Logs subfolder in instance directory.", - "desktop.settings.dailyCost": "Daily Budget ($ USD)", - "desktop.settings.dailyTokens": "Daily Budget (Tokens)", - "desktop.settings.general": "GENERAL", - "desktop.settings.instancesDir": "Instances Directory", - "desktop.settings.minLogLevel": "Minimum Log Level", - "desktop.settings.openRouterUrl": "OpenRouter Base URL", - "desktop.settings.language": "Language", - "desktop.settings.dcAndLicense": "DEPLOYMENTCENTER & LICENSE", - "desktop.settings.dcUrl": "Server URL", - "desktop.settings.dcToken": "Master Token", - "desktop.settings.dcEnv": "Environment", - "desktop.settings.updateChannel": "Update Channel", - "desktop.settings.licenseKey": "License Key", - "desktop.settings.errorReporting": "Automatically report errors to Deploymentcenter", - "desktop.settings.updateCheck": "Check for updates automatically on startup", - "desktop.settings.saved": "Settings and instance configuration saved successfully.", - "desktop.settings.savedLogRestart": "Saved. The log directory will take effect upon next restart.", - - "desktop.info.kickerApp": "APPLICATION", - "desktop.info.build": "Build", - "desktop.info.version": "Version", - "desktop.info.buildSummary": "Build Summary", - "desktop.info.kickerInstance": "INSTANCE", - "desktop.info.currentInstance": "Current Instance", - "desktop.info.openFolder": "Open Instance Folder", - "desktop.info.name": "Name", - "desktop.info.id": "ID", - "desktop.info.path": "Path", - "desktop.info.logDir": "Log Directory", - "desktop.info.openRouter": "OpenRouter", - "desktop.info.kickerModules": "MODULES", - "desktop.info.assemblies": "Assemblies", - "desktop.info.thModule": "MODULE", - "desktop.info.thBuild": "BUILD", - "desktop.info.thBuildDate": "BUILD DATE", - "desktop.info.thChanges": "CHANGES", - - "desktop.dialog.addAgent": "Create New Agent", - "desktop.dialog.agentId": "Agent ID (unique key):", - "desktop.dialog.agentDisplayName": "Display Name:", - "desktop.dialog.defaultModel": "Default Model:", - "desktop.dialog.roleDescription": "Description / Role:", - "desktop.dialog.addJobTitle": "Add / Edit Job", - "desktop.dialog.jobType": "Job Type:", - "desktop.dialog.agentWakeup": "Agent Wakeup (Periodic Execution)", - "desktop.dialog.toolJob": "Tool Job (Tool-specific Job)", - "desktop.dialog.jobTypeId": "Job Type ID / Name:", - "desktop.dialog.taskMessage": "Task Description / Message:", - "desktop.dialog.cronExpression": "Cron Expression:", - "desktop.dialog.cronHint": "Syntax: Min Hour Day Month Weekday (e.g. '*/15 * * * *' every 15 minutes)", - "desktop.dialog.runOnStart": "Run once immediately on application startup", - "desktop.dialog.addServiceTitle": "Add Service", - "desktop.dialog.serviceName": "Service Name:", - "desktop.dialog.serviceType": "Type:", - "desktop.dialog.servicePort": "Port:", - "desktop.dialog.serviceDesc": "Description:", - "desktop.dialog.restoreTitle": "Restore Backup", - "desktop.dialog.backupInfo": "Backup Information", - "desktop.dialog.backupInstance": "Instance: {0}", - "desktop.dialog.backupCreated": "Created: {0:g}", - "desktop.dialog.backupFiles": "Files: {0}", - "desktop.dialog.backupSecrets": "Credentials: {0}", - "desktop.dialog.targetDir": "Target Directory:", - "desktop.dialog.chooseFolder": "Choose Folder", - "desktop.dialog.restoreHint": "Note: It is recommended to restore into a new folder to avoid conflicts with running processes.", - "desktop.dialog.passphrase": "Passphrase:", - "desktop.dialog.passphraseProtected": "This backup contains protected credentials.", - "desktop.dialog.overwriteExisting": "Overwrite existing files in target folder", - "desktop.dialog.licenseTitle": "ClawdDotNet – License", - "desktop.dialog.licenseKey": "License Key", - "desktop.dialog.hardwareId": "Hardware ID (for support):", - "desktop.dialog.verify": "Verify", - "desktop.dialog.textEditorTitle": "Edit Text", - - "desktop.instancePicker.titleSwitch": "Switch Instance", - "desktop.instancePicker.titleSelect": "Choose Instance", - "desktop.instancePicker.hintSwitch": "Each instance runs independently with its own agents and data. Switching restarts ClawdDotNet with the selected instance.", - "desktop.instancePicker.hintSelect": "Each instance runs independently with its own agents and data.", - "desktop.instancePicker.confirmSwitch": "Switch", - "desktop.instancePicker.confirmStart": "Start", - "desktop.instancePicker.newInstancePlaceholder": "Name of new instance", - "desktop.instancePicker.create": "Create", - "desktop.instancePicker.active": "Active", - "desktop.instancePicker.dirLabel": "Directory: {0}", - "desktop.instancePicker.agentsCount": "{0} Agents · API Key {1}", - "desktop.instancePicker.apiKeyConfigured": "configured", - "desktop.instancePicker.apiKeyMissing": "missing", - "desktop.instancePicker.tooltipConfigured": "API key configured", - "desktop.instancePicker.tooltipMissing": "No API key — agents remain inactive", - "desktop.instancePicker.nameRequired": "Please enter an instance name.", - "desktop.instancePicker.createFailed": "Instance could not be created: {0}", - - "desktop.startMode.title": "ClawdDotNet – Select Start Mode", - "desktop.startMode.question": "How would you like to start ClawdDotNet?", - "desktop.startMode.managerBtn": "Launch Instance Manager (Recommended)", - "desktop.startMode.standaloneBtn": "Start as Standalone Instance", - "desktop.startMode.explanation": "• Instance Manager (Recommended):\n Starts the central background manager and opens management in your browser. Enables stable parallel operation of multiple instances without crash risks.\n\n• Standalone Mode:\n Starts exactly one instance directly as a single desktop window.", - - "desktop.standaloneSwitch.title": "ClawdDotNet – Instance Switch (Standalone)", - "desktop.standaloneSwitch.warning": "Attention: Standalone Mode", - "desktop.standaloneSwitch.text": "This instance runs standalone without the Instance Manager.\n\nIf you switch instances here, this instance will be fully stopped and all running agents and background services will end.\n\nRecommendation: Launch the Instance Manager instead to run multiple instances concurrently and independently.", - "desktop.standaloneSwitch.switchAnyway": "Switch Instance Anyway", - - "desktop.toolSettings.noSettings": "This tool does not require additional settings.", - "desktop.toolSettings.host": "Host", - "desktop.toolSettings.port": "Port", - "desktop.toolSettings.username": "Username", - "desktop.toolSettings.password": "Password", - "desktop.toolSettings.rootPath": "Root Path", - "desktop.toolSettings.imapHost": "IMAP Host", - "desktop.toolSettings.imapPort": "IMAP Port", - "desktop.toolSettings.smtpHost": "SMTP Host", - "desktop.toolSettings.smtpPort": "SMTP Port", - "desktop.toolSettings.allowedRecipients": "Allowed Recipients", - "desktop.toolSettings.type": "Type", - "desktop.toolSettings.connectionString": "Connection String", - "desktop.toolSettings.accessLevel": "Access Level", - "desktop.toolSettings.allowedTables": "Allowed Tables", - "desktop.toolSettings.botToken": "Bot Token", - "desktop.toolSettings.defaultChatId": "Default Chat ID", - "desktop.toolSettings.allowedChatIds": "Allowed Chat IDs", - "desktop.toolSettings.defaultProvider": "Default Provider", - "desktop.toolSettings.cacheTtl": "Cache TTL (seconds)", - "desktop.toolSettings.twelveDataKey": "Twelve Data Key", - "desktop.toolSettings.alphaVantageKey": "Alpha Vantage Key", - "desktop.toolSettings.allowedDomains": "Allowed Domains", - "desktop.toolSettings.maxResponseKb": "Max Response Size (KB)", - "desktop.toolSettings.userAgent": "User Agent", - "desktop.toolSettings.xApiKey": "X (Twitter) API Key", - "desktop.toolSettings.xAccounts": "X Accounts", - "desktop.toolSettings.subreddits": "Subreddits", - "desktop.toolSettings.redditPostLimit": "Reddit Post Limit", - "desktop.toolSettings.openRouterKey": "OpenRouter Key", - "desktop.toolSettings.sttModel": "STT Model", - "desktop.toolSettings.youtubeChannels": "YouTube Channels", - "desktop.toolSettings.fileRwPersonalExt": "Allowed File Extensions (personal)", - "desktop.toolSettings.fileRwSharedAccess": "Access Level (shared)", - "desktop.toolSettings.fileRwSharedExt": "Allowed File Extensions (shared)", - "desktop.toolSettings.fileRwProtectedPaths": "Protected Paths", - - "nav.chat": "Chat", - "nav.agents": "Agents", - "nav.tasks": "Tasks", - "nav.usage": "Token Usage", - "nav.agentChats": "Agent Chats", - "nav.backup": "Backup", - "nav.logs": "Logs", - "nav.settings": "Settings", - "nav.info": "Info", - - "common.all": "All", - "common.save": "Save", - "common.cancel": "Cancel", - "common.delete": "Delete", - "common.edit": "Edit", - "common.refresh": "Refresh", - "common.close": "Close", - "common.discard": "Discard", - "common.ready": "Ready", - "common.loading": "Loading…", - "common.create": "Create", - "common.add": "Add", - "common.apply": "Apply", - "common.ok": "OK", - "common.exit": "Exit" -} diff --git a/src/ClawdDotNet.Manager.Web/Endpoints.cs b/src/ClawdDotNet.Manager.Web/Endpoints.cs index 0bbb055..7cbdfa3 100644 --- a/src/ClawdDotNet.Manager.Web/Endpoints.cs +++ b/src/ClawdDotNet.Manager.Web/Endpoints.cs @@ -164,25 +164,6 @@ internal static class ManagerEndpoints }; }); - // Der Wechsel, wie E-M2 ihn meint: Alle laufen, eine kommt nach vorn. Frueher - // hiess "Instanz wechseln", dass sich der laufende Prozess herunterfaehrt und mit - // einer anderen Instanz neu startet - wer wechselte, beendete zwangslaeufig die - // Instanz, aus der heraus er es tat. - verwaltung.MapPost("/instanzen/{id}/fenster", async ( - string id, ManagerCore manager, InstanceRegistry registry, CancellationToken ct) => - { - if (Find(registry, id) is not { } instanz) - return Results.NotFound(new OutcomeDto(false, $"Es gibt keine Instanz '{id}'.")); - - return await manager.FocusInstanceAsync(instanz.Directory, ct) - ? Results.Ok(new OutcomeDto(true, $"Fenster von '{instanz.Name}' nach vorn geholt.")) - : Results.Json( - new OutcomeDto(false, - $"Instanz '{instanz.Name}' hat kein Fenster nach vorn zu holen — " - + "sie läuft nicht oder läuft kopflos."), - statusCode: StatusCodes.Status409Conflict); - }); - verwaltung.MapPost("/instanzen/{id}/stop", async ( string id, ManagerCore manager, InstanceRegistry registry, CancellationToken ct) => { diff --git a/src/ClawdDotNet.Manager.Web/wwwroot/i18n/de.json b/src/ClawdDotNet.Manager.Web/wwwroot/i18n/de.json index 050b919..eeaf256 100644 --- a/src/ClawdDotNet.Manager.Web/wwwroot/i18n/de.json +++ b/src/ClawdDotNet.Manager.Web/wwwroot/i18n/de.json @@ -781,7 +781,6 @@ "instances.selectActive": "Als aktiv wählen", "instances.start": "Starten", "instances.stop": "Beenden", - "instances.bringToFront": "Fenster nach vorn", "instances.createTitle": "Neue Instanz anlegen", "instances.instanceOfflineError": "Die Instanz ist nicht erreichbar.", "instances.noInstanceActiveError": "Keine Instanz aktiv. Unter 'Instanzen' starten oder auswählen.", diff --git a/src/ClawdDotNet.Manager.Web/wwwroot/i18n/en.json b/src/ClawdDotNet.Manager.Web/wwwroot/i18n/en.json index 3404d67..8be69d6 100644 --- a/src/ClawdDotNet.Manager.Web/wwwroot/i18n/en.json +++ b/src/ClawdDotNet.Manager.Web/wwwroot/i18n/en.json @@ -781,7 +781,6 @@ "instances.selectActive": "Select as active", "instances.start": "Start", "instances.stop": "Stop", - "instances.bringToFront": "Bring window to front", "instances.createTitle": "Create New Instance", "instances.instanceOfflineError": "The instance is not reachable.", "instances.noInstanceActiveError": "No instance is active. Start or select one under 'Instances'.", diff --git a/src/ClawdDotNet.Manager.Web/wwwroot/views/instances.js b/src/ClawdDotNet.Manager.Web/wwwroot/views/instances.js index 4fbf8ac..b582b16 100644 --- a/src/ClawdDotNet.Manager.Web/wwwroot/views/instances.js +++ b/src/ClawdDotNet.Manager.Web/wwwroot/views/instances.js @@ -176,19 +176,7 @@ async function ladeInstanzen(istHintergrund = false) { erstelleElement("span", { text: " " + t("instances.stop") }) ); - const fensterBtn = erstelleElement( - "button", - { - klasse: "schaltflaeche flach klein", - disabled: !istLaufend, - title: t("instances.bringToFront"), - onclick: () => holeFensterNachVorn(instanz) - }, - erstelleIcon(PFADE.fenster, 14), - erstelleElement("span", { text: " " + t("instances.bringToFront") }) - ); - - fussAktionen.append(waehlenBtn, startenBtn, anhaltenBtn, fensterBtn); + fussAktionen.append(waehlenBtn, startenBtn, anhaltenBtn); const karte = erstelleKarte(instanz.name, [dl, fussAktionen], { aktionen: karteKopfAktionen, @@ -336,17 +324,6 @@ function oeffneSicherheitsStoppDialog(instanz) { modal.oeffnen(); } -async function holeFensterNachVorn(instanz) { - try { - const antwort = await api(`/verwaltung/instanzen/${encodeURIComponent(instanz.id)}/fenster`, { - method: "POST" - }); - zeigeMeldung(antwort?.meldung || `Brought '${instanz.name}' to front.`, "info"); - } catch (err) { - zeigeMeldung(`Window focus failed: ${err.message}`, "warnung"); - } -} - function oeffneNeueInstanzDialog() { const formular = erstelleElement("form", { klasse: "formular-raster", diff --git a/src/ClawdDotNet.Manager/InstanceChannel.cs b/src/ClawdDotNet.Manager/InstanceChannel.cs index ff39826..75ff499 100644 --- a/src/ClawdDotNet.Manager/InstanceChannel.cs +++ b/src/ClawdDotNet.Manager/InstanceChannel.cs @@ -58,14 +58,6 @@ public interface IInstanceChannel /// Socket. ///
Task RequestStopAsync(string instanceDirectory, CancellationToken ct = default); - - /// - /// Bittet die Instanz, ihr Fenster nach vorn zu holen (E-M2). - /// - /// false heißt: Die Bitte kam nicht an, oder diese Instanz hat kein - /// Fenster — sie läuft kopflos. Beides ist kein Fehler, sondern eine Auskunft. - /// - Task RequestFocusAsync(string instanceDirectory, CancellationToken ct = default); } /// @@ -135,10 +127,6 @@ public sealed class SocketInstanceChannel(TimeSpan? timeout = null) : IInstanceC } } - public Task RequestFocusAsync( - string instanceDirectory, CancellationToken ct = default) - => PostAsync(instanceDirectory, "/api/instanz/fenster", ct); - public Task RequestStopAsync( string instanceDirectory, CancellationToken ct = default) => PostAsync(instanceDirectory, "/api/instanz/beenden", ct); diff --git a/src/ClawdDotNet.Manager/InstanceLauncher.cs b/src/ClawdDotNet.Manager/InstanceLauncher.cs index 8790369..49f8599 100644 --- a/src/ClawdDotNet.Manager/InstanceLauncher.cs +++ b/src/ClawdDotNet.Manager/InstanceLauncher.cs @@ -56,11 +56,14 @@ public interface IInstanceLauncher /// Auf einer Maschine ohne Bildschirmsitzung gibt es keines, und dann ist kopflos die /// einzige Betriebsart, die trägt. /// +/// #764: Seit die Fenster entfernt sind, ist kopflos die einzige Betriebsart — +/// --headless geht immer mit. +/// /// --managed geht immer mit. Daran erkennt die Instanz, dass sie /// geführt wird, und bietet den Instanzwechsel nicht mehr selbst an: Der wäre ein /// Selbst-Neustart und nähme genau die Instanz mit, aus der heraus jemand wechselt. /// -public sealed class ProcessInstanceLauncher(string executablePath, bool headless = true) +public sealed class ProcessInstanceLauncher(string executablePath) : IInstanceLauncher { /// Wo die Programmdatei liegt — in der Regel neben der des Managers. @@ -87,7 +90,7 @@ public sealed class ProcessInstanceLauncher(string executablePath, bool headless CreateNoWindow = true }; - if (headless) start.ArgumentList.Add("--headless"); + start.ArgumentList.Add("--headless"); start.ArgumentList.Add("--managed"); start.ArgumentList.Add("--instance"); diff --git a/src/ClawdDotNet.Manager/InstanceRegistry.cs b/src/ClawdDotNet.Manager/InstanceRegistry.cs index 8cf33cc..a0b4ce3 100644 --- a/src/ClawdDotNet.Manager/InstanceRegistry.cs +++ b/src/ClawdDotNet.Manager/InstanceRegistry.cs @@ -215,28 +215,6 @@ public sealed class InstanceRegistry : IAsyncDisposable public Task StopAsync(string instanceDirectory, CancellationToken ct = default) => Find(instanceDirectory).StopAsync(ct); - /// - /// Holt das Fenster einer Instanz nach vorn — der Wechsel, wie E-M2 ihn meint. - /// - /// Das ist der Ersatz für den Selbst-Neustart. Vorher hiess „Instanz - /// wechseln": Der laufende Prozess fährt sich herunter und startet sich mit einer - /// anderen Instanz neu — wer wechselte, beendete zwangsläufig die Instanz, aus der - /// heraus er es tat. Jetzt laufen alle, und es kommt nur eine nach vorn. - /// - /// false heisst: Sie läuft nicht, sie hört nicht, oder sie hat kein - /// Fenster. - /// - public async Task FocusAsync(string instanceDirectory, CancellationToken ct = default) - { - var aufsicht = Find(instanceDirectory); - - if (aufsicht.Condition != InstanceCondition.Running) - return false; - - return await _channel.RequestFocusAsync(aufsicht.InstanceDirectory, ct) - .ConfigureAwait(false); - } - /// /// Hält alle laufenden Instanzen an. Nicht beim Beenden des Managers, sondern /// nur, wenn es einen Grund gibt, der sie alle betrifft — ein Lizenzwiderruf. diff --git a/src/ClawdDotNet.Manager/ManagerCore.cs b/src/ClawdDotNet.Manager/ManagerCore.cs index 2ebef3d..1bc19d3 100644 --- a/src/ClawdDotNet.Manager/ManagerCore.cs +++ b/src/ClawdDotNet.Manager/ManagerCore.cs @@ -298,9 +298,6 @@ public sealed class ManagerCore : IAsyncDisposable public Task StopInstanceAsync(string instanceDirectory, CancellationToken ct = default) => Instances.StopAsync(instanceDirectory, ct); - /// - public Task FocusInstanceAsync(string instanceDirectory, CancellationToken ct = default) - => Instances.FocusAsync(instanceDirectory, ct); // ─── Das Urteil ─── diff --git a/src/ClawdDotNet.Manager/ManagerSettings.cs b/src/ClawdDotNet.Manager/ManagerSettings.cs index ecf7759..c7df709 100644 --- a/src/ClawdDotNet.Manager/ManagerSettings.cs +++ b/src/ClawdDotNet.Manager/ManagerSettings.cs @@ -47,6 +47,11 @@ public sealed class ManagerSettings /// Bildschirmsitzung — einem Server, einem Bauknecht — gehört hier false hin; /// dann laufen die Instanzen kopflos und sind nur über die Weboberfläche zu /// bedienen. + /// + /// #764: wird nicht mehr ausgewertet. Die Avalonia-Fenster sind entfernt; + /// jede Instanz läuft kopflos. Der Schlüssel bleibt lesbar, damit eine bestehende + /// manager.json ihn nicht als unbekannt mitschleppt oder beim Laden scheitert — + /// gelöscht wird er beim nächsten Speichern nicht, er tut nur nichts mehr. /// [JsonPropertyName("instanceWindows")] public bool InstanceWindows { get; set; } = true; diff --git a/src/ClawdDotNet.ManagerApp/Program.cs b/src/ClawdDotNet.ManagerApp/Program.cs index 9eed6d9..a4e6fdf 100644 --- a/src/ClawdDotNet.ManagerApp/Program.cs +++ b/src/ClawdDotNet.ManagerApp/Program.cs @@ -73,8 +73,7 @@ internal static class Program : settings.Settings.InstanceExecutable); logger.LogInformation( - "Instanzen laufen {Art}. Neustart nach Absturz: hoechstens {Grenze} in {Fenster}.", - settings.Settings.InstanceWindows ? "mit eigenem Fenster" : "ohne Fenster", + "Instanzen laufen ohne Fenster. Neustart nach Absturz: hoechstens {Grenze} in {Fenster}.", settings.Settings.ToRestartPolicy().MaxRestarts, settings.Settings.ToRestartPolicy().Window); @@ -166,7 +165,7 @@ internal static class Program Path.GetFullPath(s.InstancesDirectory)); var launcher = new ProcessInstanceLauncher( - ResolveInstanceExecutable(s, logger), headless: !s.InstanceWindows); + ResolveInstanceExecutable(s, logger)); var channel = new SocketInstanceChannel(); var registry = new InstanceRegistry( diff --git a/src/ClawdDotNet.Web/Endpoints/ControlEndpoints.cs b/src/ClawdDotNet.Web/Endpoints/ControlEndpoints.cs index ae01b94..edea8a6 100644 --- a/src/ClawdDotNet.Web/Endpoints/ControlEndpoints.cs +++ b/src/ClawdDotNet.Web/Endpoints/ControlEndpoints.cs @@ -40,6 +40,9 @@ public sealed record PulsDto( /// Der Endpunkt löst aus, der Wirtsprozess reagiert. Und wer reagiert, ist verschieden — /// kopflos die Warteschleife in HeadlessRun, mit Fenster die /// Avalonia-Anwendung. +/// +/// #764: Seit die Avalonia-Fenster entfernt sind, ist HeadlessRun der einzige +/// Wirt. Mit den Fenstern ging auch „Fenster nach vorn holen" (E-M2): Es gibt keines mehr. ///
public sealed class InstanceControl { @@ -48,14 +51,6 @@ public sealed class InstanceControl /// Der Manager bittet, diesen Prozess zu beenden. public event Action? ShutdownRequested; - /// - /// Der Manager bittet, das Fenster dieser Instanz nach vorn zu holen (E-M2). - /// - /// Kopflos gibt es nichts nach vorn zu holen; dann läuft dieses Ereignis ins - /// Leere, und das ist die richtige Antwort. - /// - public event Action? FocusRequested; - /// /// Meldet den Wunsch zu enden an. Ein zweiter Aufruf tut nichts — sonst stiesse er /// mitten im Herunterfahren ein zweites Herunterfahren an. @@ -69,11 +64,6 @@ public sealed class InstanceControl return true; } - /// - /// Holt das Fenster nach vorn. Beliebig oft — anders als beim Beenden ist die - /// Wiederholung hier der Normalfall: Jeder Wechsel auf diese Instanz ist einer. - /// - public void RequestFocus() => FocusRequested?.Invoke(); } /// @@ -83,8 +73,8 @@ public sealed class InstanceControl /// Endpunkte nicht, auch mit gültigem Token nicht, und sie antworten dort mit 404 statt /// mit 403: Was es nicht gibt, muss man auch nicht erklären. Der Grund ist der Schnitt aus /// #528 — die Lebensdauer einer Instanz gehört dem Instanzmanager. Eine Browsersitzung -/// soll den Prozess, der sie gerade bedient, nicht beenden und auch nicht sein Fenster -/// aufreissen können; der Manager soll es, und er kommt über den Socket. +/// soll den Prozess, der sie gerade bedient, nicht beenden können (bis #764 auch nicht sein +/// Fenster aufreissen); der Manager soll es, und er kommt über den Socket. /// internal static class ControlEndpoints { @@ -130,18 +120,5 @@ internal static class ControlEndpoints // 202 und nicht 200: Beim Antworten laeuft der Prozess noch. return Results.Accepted(value: new { angenommen = true }); }); - - control.MapPost("/fenster", (HttpContext context, InstanceControl steuerung) => - { - if (!LocalTransport.Applies(context)) - return Results.NotFound(); - - // Hier ohne OnCompleted: Das Fenster nach vorn zu holen beendet nichts, die - // Antwort geht ohnehin raus. Und der Manager soll gleich erfahren, ob dieser - // Prozess ueberhaupt eines hat. - steuerung.RequestFocus(); - - return Results.Ok(new { angenommen = true }); - }); } } diff --git a/src/ClawdDotNet.Web/InstanceHttpHost.cs b/src/ClawdDotNet.Web/InstanceHttpHost.cs index dd22ddc..c1f8e9b 100644 --- a/src/ClawdDotNet.Web/InstanceHttpHost.cs +++ b/src/ClawdDotNet.Web/InstanceHttpHost.cs @@ -56,8 +56,8 @@ public sealed class InstanceHttpHost : IAsyncDisposable /// /// Was der Instanzmanager diesem Prozess über den Socket sagen kann: sich beenden - /// (POST /api/instanz/beenden) oder sein Fenster nach vorn holen - /// (POST /api/instanz/fenster). + /// (POST /api/instanz/beenden). Bis #764 auch: sein Fenster nach vorn holen — + /// das Fenster gibt es nicht mehr. /// /// Der Wirtsprozess hängt sich hier an und tut es: kopflos beendet sich die /// Warteschleife, mit Fenster reagiert die Avalonia-Anwendung. Diese Klasse tut es diff --git a/tests/ClawdDotNet.Manager.Tests/Doubles.cs b/tests/ClawdDotNet.Manager.Tests/Doubles.cs index 4880cf8..4ca4b68 100644 --- a/tests/ClawdDotNet.Manager.Tests/Doubles.cs +++ b/tests/ClawdDotNet.Manager.Tests/Doubles.cs @@ -186,16 +186,4 @@ internal sealed class FakeChannel : IInstanceChannel OnStopRequest?.Invoke(instanceDirectory); return Task.FromResult(StopRequestArrives); } - - /// Welche Instanzen gebeten wurden, ihr Fenster nach vorn zu holen. - public List FocusRequests { get; } = []; - - /// Ob die Instanz ein Fenster hat, das nach vorn kommen kann. - public bool HasWindow { get; set; } = true; - - public Task RequestFocusAsync(string instanceDirectory, CancellationToken ct = default) - { - FocusRequests.Add(Path.GetFullPath(instanceDirectory)); - return Task.FromResult(HasWindow); - } } diff --git a/tests/ClawdDotNet.Manager.Tests/ManagerCoreTests.cs b/tests/ClawdDotNet.Manager.Tests/ManagerCoreTests.cs index 24c3356..ea47bd9 100644 --- a/tests/ClawdDotNet.Manager.Tests/ManagerCoreTests.cs +++ b/tests/ClawdDotNet.Manager.Tests/ManagerCoreTests.cs @@ -222,98 +222,3 @@ public sealed class ManagerCoreTests : IAsyncDisposable (await manager.StartInstanceAsync(pfad)).ShouldBe(StartRefusal.DidNotStart); } } - -/// -/// Der Wechsel, wie E-M2 ihn meint (#528, Stufe 5). -/// -/// Vorher hiess „Instanz wechseln": Der laufende Prozess fährt sich herunter -/// und startet sich mit einer anderen Instanz neu. Wer wechselte, beendete zwangsläufig -/// die Instanz, aus der heraus er es tat — und genau dabei hat sich am 2026-09-08 die -/// Anwendung aufgehängt (#529). Jetzt laufen alle, und es kommt nur eine nach vorn. -/// -public sealed class InstanceFocusTests : IAsyncDisposable -{ - private readonly string _root = Path.Combine( - Path.GetTempPath(), "clawd-tests", "focus-" + Guid.NewGuid().ToString("N")[..8]); - - private readonly FakeLauncher _launcher = new(); - private readonly FakeChannel _kanal = new(); - private readonly InstanceDirectoryManager _verzeichnisse; - - private static readonly SupervisionOptions Options = new( - ProbeInterval: TimeSpan.FromMilliseconds(50), - StartTimeout: TimeSpan.FromMilliseconds(600), - SilentChecksBeforeAlarm: 3, - StopGrace: TimeSpan.FromMilliseconds(300), - SilentKillGrace: TimeSpan.FromMilliseconds(300), - MaxDrainWait: TimeSpan.FromSeconds(2)); - - public InstanceFocusTests() - { - Directory.CreateDirectory(_root); - _verzeichnisse = new InstanceDirectoryManager(Path.Combine(_root, "Instances")); - // Der Socket antwortet nur, wenn wirklich ein Prozess laeuft - genau wie im - // Betrieb (siehe FakeChannel.Launcher). - _kanal.Launcher = _launcher; - } - - private InstanceRegistry Register() => new( - _verzeichnisse, _launcher, _kanal, NullLoggerFactory.Instance, Options); - - public async ValueTask DisposeAsync() - { - await Task.CompletedTask; - try { Directory.Delete(_root, recursive: true); } - catch { /* Ein liegengebliebener Testordner faerbt keinen Lauf rot. */ } - } - - [Fact] - public async Task Eine_laufende_Instanz_wird_nach_vorn_geholt() - { - await using var register = Register(); - var pfad = register.Create("Alpha"); - - _kanal.AnswerFor[Path.GetFullPath(pfad)] = new InstanceIdentity("i-1", "Alpha", "0.1.2"); - await register.StartAsync(pfad); - - (await register.FocusAsync(pfad)).ShouldBeTrue(); - - _kanal.FocusRequests.ShouldBe([Path.GetFullPath(pfad)]); - - // Und vor allem: Es wurde nichts beendet und nichts neu gestartet. - _launcher.Starts.ShouldBe(1); - _kanal.StopRequests.ShouldBe(0); - _launcher.Last!.HasExited.ShouldBeFalse(); - } - - [Fact] - public async Task Eine_Instanz_die_nicht_laeuft_hat_kein_Fenster() - { - await using var register = Register(); - var pfad = register.Create("Alpha"); - - (await register.FocusAsync(pfad)).ShouldBeFalse(); - - // Nicht einmal gefragt: Wer nicht laeuft, antwortet auch nicht. - _kanal.FocusRequests.ShouldBeEmpty(); - } - - /// - /// Eine kopflose Instanz hat nichts nach vorn zu holen — und sagt das, statt Erfolg - /// zu melden. - /// - [Fact] - public async Task Eine_kopflose_Instanz_meldet_dass_sie_kein_Fenster_hat() - { - await using var register = Register(); - var pfad = register.Create("Alpha"); - - _kanal.AnswerFor[Path.GetFullPath(pfad)] = new InstanceIdentity("i-1", "Alpha", "0.1.2"); - await register.StartAsync(pfad); - - _kanal.HasWindow = false; - - (await register.FocusAsync(pfad)).ShouldBeFalse(); - _kanal.FocusRequests.ShouldHaveSingleItem(); - } -} diff --git a/tests/ClawdDotNet.Web.Tests/InstanceSocketTests.cs b/tests/ClawdDotNet.Web.Tests/InstanceSocketTests.cs index fd626f0..c6ad92f 100644 --- a/tests/ClawdDotNet.Web.Tests/InstanceSocketTests.cs +++ b/tests/ClawdDotNet.Web.Tests/InstanceSocketTests.cs @@ -247,27 +247,6 @@ public sealed class InstanceControlTests : IDisposable return port; } - [Fact] - public async Task Ueber_den_Socket_kommt_die_Bitte_um_das_Fenster_an() - { - await using var host = NeuerHost(FreierPort()); - await using var web = InstanceHttpHost.TryStart(host, NullLoggerFactory.Instance); - - web.ShouldNotBeNull(); - - var gebeten = 0; - web!.Control.FocusRequested += () => Interlocked.Increment(ref gebeten); - - using var client = InstanceEndpoint.CreateClient(host.InstancePath); - (await client.PostAsync("/api/instanz/fenster", content: null)).EnsureSuccessStatusCode(); - - gebeten.ShouldBe(1); - - // Und beliebig oft: Jeder Wechsel auf diese Instanz ist einer. - (await client.PostAsync("/api/instanz/fenster", content: null)).EnsureSuccessStatusCode(); - gebeten.ShouldBe(2); - } - [Fact] public async Task Ueber_TCP_gibt_es_die_Steuerung_nicht() { @@ -280,15 +259,12 @@ public sealed class InstanceControlTests : IDisposable web!.Url.ShouldNotBeNull(); var gebeten = false; - web.Control.FocusRequested += () => gebeten = true; + web.Control.ShutdownRequested += () => gebeten = true; using var client = new HttpClient { BaseAddress = new Uri($"http://127.0.0.1:{port}") }; client.DefaultRequestHeaders.Add("Authorization", $"Bearer {Token}"); // Mit gueltigem Token - und trotzdem nicht vorhanden. - (await client.PostAsync("/api/instanz/fenster", content: null)).StatusCode - .ShouldBe(System.Net.HttpStatusCode.NotFound); - (await client.PostAsync("/api/instanz/beenden", content: null)).StatusCode .ShouldBe(System.Net.HttpStatusCode.NotFound);