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

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

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

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

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

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-08-23 12:16:05 +02:00
co-authored by Claude Opus 5
parent b5bf97ae74
commit 33d95a6c3f
88 changed files with 11665 additions and 1029 deletions
@@ -0,0 +1,239 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:ClawdDotNet.Desktop.ViewModels"
xmlns:conv="using:ClawdDotNet.Desktop.Converters"
mc:Ignorable="d" d:DesignWidth="520" d:DesignHeight="420"
x:Class="ClawdDotNet.Desktop.Views.ToolSettingsView"
x:DataType="vm:ToolSettingsViewModel">
<!--
Die Felder eines Werkzeugs — im Entwurf unten rechts auf der Agenten-Seite, nicht
mehr in einem eigenen Fenster. Deshalb ein UserControl und kein Window: Der Inhalt
ist derselbe, der Rahmen drumherum entscheidet der Aufrufer.
Flach statt in Karten und ohne verschachtelte Registerkarten (siehe
Implementierungsleitfaden im Mockup-Verzeichnis): Beschriftung ueber dem Feld,
hoechstens zwei Spalten.
-->
<StackPanel Spacing="12" MaxWidth="520" HorizontalAlignment="Left">
<!-- 1. FTP -->
<StackPanel Spacing="12" IsVisible="{Binding ToolName,
Converter={x:Static conv:ToolMatchConverter.Instance}, ConverterParameter=FTP}">
<StackPanel>
<TextBlock Classes="label" Text="Host" />
<TextBox Text="{Binding FtpHost}" PlaceholderText="ftp.example.com" />
</StackPanel>
<Grid ColumnDefinitions="*,12,*">
<StackPanel Grid.Column="0">
<TextBlock Classes="label" Text="Port" />
<TextBox Text="{Binding FtpPort}" />
</StackPanel>
<StackPanel Grid.Column="2">
<TextBlock Classes="label" Text="Benutzername" />
<TextBox Text="{Binding FtpUsername}" />
</StackPanel>
</Grid>
<StackPanel>
<TextBlock Classes="label" Text="Passwort" />
<TextBox Text="{Binding FtpPassword}" PasswordChar="•" />
</StackPanel>
<StackPanel>
<TextBlock Classes="label" Text="Root-Pfad" />
<TextBox Text="{Binding FtpRootPath}" />
</StackPanel>
</StackPanel>
<!-- 2. Mail -->
<StackPanel Spacing="12" IsVisible="{Binding ToolName,
Converter={x:Static conv:ToolMatchConverter.Instance}, ConverterParameter=Mail}">
<Grid ColumnDefinitions="*,12,*">
<StackPanel Grid.Column="0">
<TextBlock Classes="label" Text="Benutzername" />
<TextBox Text="{Binding MailUsername}" />
</StackPanel>
<StackPanel Grid.Column="2">
<TextBlock Classes="label" Text="Passwort" />
<TextBox Text="{Binding MailPassword}" PasswordChar="•" />
</StackPanel>
</Grid>
<Grid ColumnDefinitions="*,12,*">
<StackPanel Grid.Column="0">
<TextBlock Classes="label" Text="IMAP-Host" />
<TextBox Text="{Binding MailImapHost}" />
</StackPanel>
<StackPanel Grid.Column="2">
<TextBlock Classes="label" Text="IMAP-Port" />
<TextBox Text="{Binding MailImapPort}" />
</StackPanel>
</Grid>
<Grid ColumnDefinitions="*,12,*">
<StackPanel Grid.Column="0">
<TextBlock Classes="label" Text="SMTP-Host" />
<TextBox Text="{Binding MailSmtpHost}" />
</StackPanel>
<StackPanel Grid.Column="2">
<TextBlock Classes="label" Text="SMTP-Port" />
<TextBox Text="{Binding MailSmtpPort}" />
</StackPanel>
</Grid>
<StackPanel>
<TextBlock Classes="label" Text="Erlaubte Empfänger" />
<TextBox Text="{Binding MailAllowedRecipients}"
PlaceholderText="adresse1@domain.de, adresse2@domain.de" />
</StackPanel>
</StackPanel>
<!-- 3. Database -->
<StackPanel Spacing="12" IsVisible="{Binding ToolName,
Converter={x:Static conv:ToolMatchConverter.Instance}, ConverterParameter=Database}">
<StackPanel>
<TextBlock Classes="label" Text="Typ" />
<ComboBox ItemsSource="{Binding DbTypes}" SelectedItem="{Binding DbType}"
HorizontalAlignment="Stretch" />
</StackPanel>
<StackPanel>
<TextBlock Classes="label" Text="Connection-String" />
<TextBox Text="{Binding DbConnectionString}" PasswordChar="•" />
</StackPanel>
<StackPanel>
<TextBlock Classes="label" Text="Zugriffsebene" />
<ComboBox ItemsSource="{Binding DbAccessLevels}" SelectedItem="{Binding DbAccessLevel}"
HorizontalAlignment="Stretch" />
</StackPanel>
<StackPanel>
<TextBlock Classes="label" Text="Erlaubte Tabellen" />
<TextBox Text="{Binding DbAllowedTables}" PlaceholderText="tabelle1, tabelle2" />
</StackPanel>
</StackPanel>
<!-- 4. Telegram -->
<StackPanel Spacing="12" IsVisible="{Binding ToolName,
Converter={x:Static conv:ToolMatchConverter.Instance}, ConverterParameter=Telegram}">
<StackPanel>
<TextBlock Classes="label" Text="Bot-Token" />
<TextBox Text="{Binding TelegramBotToken}" PasswordChar="•" />
</StackPanel>
<StackPanel>
<TextBlock Classes="label" Text="Standard Chat-ID" />
<TextBox Text="{Binding TelegramDefaultChatId}" />
</StackPanel>
<StackPanel>
<TextBlock Classes="label" Text="Erlaubte Chat-IDs" />
<TextBox Text="{Binding TelegramAllowedChatIds}" PlaceholderText="id1, id2" />
</StackPanel>
</StackPanel>
<!-- 5. DirectAPI -->
<StackPanel Spacing="12" IsVisible="{Binding ToolName,
Converter={x:Static conv:ToolMatchConverter.Instance}, ConverterParameter=DirectAPI}">
<Grid ColumnDefinitions="*,12,*">
<StackPanel Grid.Column="0">
<TextBlock Classes="label" Text="Standard-Provider" />
<TextBox Text="{Binding DirectApiDefaultProvider}" />
</StackPanel>
<StackPanel Grid.Column="2">
<TextBlock Classes="label" Text="Cache TTL (Sekunden)" />
<TextBox Text="{Binding DirectApiCacheTtlSeconds}" />
</StackPanel>
</Grid>
<StackPanel>
<TextBlock Classes="label" Text="Twelve Data Key" />
<TextBox Text="{Binding DirectApiTwelveDataKey}" PasswordChar="•" />
</StackPanel>
<StackPanel>
<TextBlock Classes="label" Text="Alpha Vantage Key" />
<TextBox Text="{Binding DirectApiAlphaVantageKey}" PasswordChar="•" />
</StackPanel>
</StackPanel>
<!-- 6. WebFetch -->
<StackPanel Spacing="12" IsVisible="{Binding ToolName,
Converter={x:Static conv:ToolMatchConverter.Instance}, ConverterParameter=WebFetch}">
<StackPanel>
<TextBlock Classes="label" Text="Erlaubte Domains" />
<TextBox Text="{Binding WebFetchAllowedDomains}"
PlaceholderText="reuters.com, coindesk.com" />
</StackPanel>
<Grid ColumnDefinitions="*,12,*">
<StackPanel Grid.Column="0">
<TextBlock Classes="label" Text="Max. Antwortgröße (KB)" />
<TextBox Text="{Binding WebFetchMaxResponseKb}" />
</StackPanel>
<StackPanel Grid.Column="2">
<TextBlock Classes="label" Text="User Agent" />
<TextBox Text="{Binding WebFetchUserAgent}" />
</StackPanel>
</Grid>
</StackPanel>
<!-- 7. SocialMediaManager -->
<StackPanel Spacing="12" IsVisible="{Binding ToolName,
Converter={x:Static conv:ToolMatchConverter.Instance}, ConverterParameter=SocialMediaManager}">
<StackPanel>
<TextBlock Classes="label" Text="X (Twitter) API-Key" />
<TextBox Text="{Binding SmmXApiKey}" PasswordChar="•" />
</StackPanel>
<StackPanel>
<TextBlock Classes="label" Text="X Accounts" />
<TextBox Text="{Binding SmmXWatchAccounts}" PlaceholderText="account1, account2" />
</StackPanel>
<Grid ColumnDefinitions="*,12,*">
<StackPanel Grid.Column="0">
<TextBlock Classes="label" Text="Subreddits" />
<TextBox Text="{Binding SmmRedditWatchSubreddits}" PlaceholderText="stocks, investing" />
</StackPanel>
<StackPanel Grid.Column="2">
<TextBlock Classes="label" Text="Reddit Post Limit" />
<TextBox Text="{Binding SmmRedditPostLimit}" />
</StackPanel>
</Grid>
<StackPanel>
<TextBlock Classes="label" Text="OpenRouter Key" />
<TextBox Text="{Binding SmmOpenRouterApiKey}" PasswordChar="•" />
</StackPanel>
<Grid ColumnDefinitions="*,12,*">
<StackPanel Grid.Column="0">
<TextBlock Classes="label" Text="STT-Modell" />
<TextBox Text="{Binding SmmSttModel}" />
</StackPanel>
<StackPanel Grid.Column="2">
<TextBlock Classes="label" Text="YouTube-Kanäle" />
<TextBox Text="{Binding SmmYoutubeChannels}" PlaceholderText="URL1, URL2" />
</StackPanel>
</Grid>
</StackPanel>
<!-- 8. FileRW -->
<StackPanel Spacing="12" IsVisible="{Binding ToolName,
Converter={x:Static conv:ToolMatchConverter.Instance}, ConverterParameter=FileRW}">
<StackPanel>
<TextBlock Classes="label" Text="Erlaubte Dateiendungen (persönlich)" />
<TextBox Text="{Binding FileRwPersonalAllowedExtensions}" />
</StackPanel>
<StackPanel>
<TextBlock Classes="label" Text="Zugriffsebene (geteilt)" />
<ComboBox ItemsSource="{Binding FileRwAccessLevels}"
SelectedItem="{Binding FileRwSharedAccessLevel}"
HorizontalAlignment="Stretch" />
</StackPanel>
<StackPanel>
<TextBlock Classes="label" Text="Erlaubte Dateiendungen (geteilt)" />
<TextBox Text="{Binding FileRwSharedAllowedExtensions}" />
</StackPanel>
<StackPanel>
<TextBlock Classes="label" Text="Geschützte Pfade" />
<TextBox Text="{Binding FileRwProtectedPaths}" />
</StackPanel>
</StackPanel>
<!-- Werkzeuge ohne weitere Einstellungen -->
<TextBlock Classes="muted" FontStyle="Italic" TextWrapping="Wrap"
Text="Dieses Werkzeug benötigt keine weiteren Einstellungen."
IsVisible="{Binding SettingsObject, Converter={x:Static ObjectConverters.IsNull}}" />
</StackPanel>
</UserControl>