Entschieden vom Benutzer am 2026-09-08. Der Schalter heisst autostartByManager und steht in InstanceSettings.json - bei der Instanz, nicht beim Manager. ZWEI DINGE IN EINEM SCHALTER, weil es dieselbe Zusage ist: Der Manager startet diese Instanz, wenn er selbst hochkommt, und er startet sie wieder, wenn sie abstuerzt. Ohne den Schalter ruehrt er nichts an - ein Manager, der nach einem Neustart der Maschine alles hochfaehrt, was er findet, startet auch das, was jemand mit Absicht angehalten hat. Ausgeschaltet vorbelegt. DER SICHERUNGSAUTOMAT ist der eigentliche Inhalt. Wieder hochzufahren ist die einfache Haelfte; die schwierige ist zu erkennen, wann man es lassen muss. Nach drei Neustarts in zehn Minuten (maxRestartsInWindow, restartWindowMinutes) setzt der Manager aus und meldet es. Die Instanz bleibt dann aus, bis jemand sie von Hand startet - und dieser Start raeumt den Zaehler ab, denn wer von Hand startet, hat entweder etwas geaendert oder weiss, was er tut. Das Zeitfenster wandert: Eine Instanz, die einmal im Monat abstuerzt und wieder hochkommt, laeuft nie in die Grenze. Nur bei einem Absturz, nicht wenn eine Instanz verstummt. Eine stumme Instanz lebt noch; sie neu zu starten hiesse, sie erst abzuschiessen, und ob der Manager das von sich aus darf, ist nicht entschieden. Als offene Frage aufgeschrieben - genau dieser Zustand war der Anlass des Vorhabens. Der Schalter steht bei der Instanz, weil er eine Eigenschaft dieser Instanz ist und weil die Instanzdatei dem Instanzprozess gehoert: Sie vom Manager schreiben zu lassen, waehrend die Instanz laeuft, waeren zwei Schreiber auf einer Datei. Der Manager liest ihn nur; geaendert wird er auf der Einstellungsseite der Instanz. EIN DEFEKT, den erst diese Tests gezeigt haben: StartAsync gab "laeuft schon" zurueck, wenn die Aufsicht die Instanz fuer laufend hielt - ohne nachzusehen. Zwischen zwei Aufsichtsdurchgaengen liegen aber Sekunden, und in denen kann sie wegbrechen. Wer in dieser Luecke "starten" verlangte, bekam einen Erfolg, hinter dem nichts stand, und der naechste Durchgang meldete einen Absturz, den niemand mehr erwartete. Jetzt wird gefragt, bevor zugestimmt wird. UND EIN TESTDOUBLE, das die Wirklichkeit nicht abbildete: Der falsche Socket antwortete unabhaengig davon, ob ein Prozess lief. Damit war jeder Testaufbau, der die Antwort vor dem Hochfahren hinterlegte, stillschweigend ein anderer Test als beabsichtigt - eine Antwort sagt dem Manager "laeuft bereits", er uebernimmt, und der Starter wird nie angefasst. Dreimal passiert. Der falsche Socket haengt jetzt am falschen Starter. Sicherungen im Manager sind als #530 zurueckgestellt, mit Ausloeser. Vorab entschieden ist dort nur eines: Zurueckspielen ausschliesslich bei inaktiver Instanz. 19 neue Tests. Build ohne Warnungen, 793 Tests gruen, 8 uebersprungen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
144 lines
6.3 KiB
XML
144 lines
6.3 KiB
XML
<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:ctrl="using:ClawdDotNet.Desktop.Controls"
|
|
mc:Ignorable="d" d:DesignWidth="1100" d:DesignHeight="740"
|
|
x:Class="ClawdDotNet.Desktop.Views.SettingsPageView"
|
|
x:DataType="vm:SettingsPageViewModel">
|
|
|
|
<DockPanel>
|
|
|
|
<!-- Aktionen unten: Der Entwurf setzt flache Felder ohne Karten, damit bleibt am
|
|
unteren Rand nur die Zeile mit Verwerfen und Speichern. -->
|
|
<Border DockPanel.Dock="Bottom" BorderBrush="{DynamicResource DividerBrush}"
|
|
BorderThickness="0,1,0,0" Padding="0,12,0,0" Margin="0,16,0,0">
|
|
<StackPanel Orientation="Horizontal" Spacing="8" HorizontalAlignment="Right">
|
|
<Button Content="Verwerfen" Command="{Binding LoadFromHostCommand}" />
|
|
<Button Classes="primary" Command="{Binding SaveSettingsCommand}">
|
|
<StackPanel Orientation="Horizontal" Spacing="6">
|
|
<ctrl:StrokeIcon Data="{StaticResource IconSave}" Width="14" Height="14" />
|
|
<TextBlock Text="Speichern" />
|
|
</StackPanel>
|
|
</Button>
|
|
</StackPanel>
|
|
</Border>
|
|
|
|
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
|
<StackPanel Spacing="26" MaxWidth="680" HorizontalAlignment="Left">
|
|
|
|
<!-- ══════════════════ Instanz ══════════════════ -->
|
|
<StackPanel Spacing="14">
|
|
<TextBlock Classes="kicker" Text="INSTANZ" />
|
|
|
|
<StackPanel>
|
|
<TextBlock Classes="label" Text="Instanz-Name" />
|
|
<TextBox Text="{Binding InstanceName}" />
|
|
</StackPanel>
|
|
|
|
<StackPanel>
|
|
<TextBlock Classes="label" Text="OpenRouter API-Key" />
|
|
<TextBox Text="{Binding OpenRouterApiKey}" PasswordChar="•" />
|
|
</StackPanel>
|
|
|
|
<StackPanel>
|
|
<CheckBox IsChecked="{Binding AutostartByManager}"
|
|
Content="Autostart durch Manager" />
|
|
<TextBlock Classes="caption" TextWrapping="Wrap" Margin="0,4,0,0"
|
|
Text="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." />
|
|
</StackPanel>
|
|
|
|
<StackPanel>
|
|
<TextBlock Classes="label" Text="Protokoll-Verzeichnis" />
|
|
<TextBox Text="{Binding LogDirectory}" />
|
|
<TextBlock Classes="caption" TextWrapping="Wrap" Margin="0,4,0,0"
|
|
Text="Gilt nur für diese Instanz. Leer heißt: Unterordner Logs im Instanzverzeichnis." />
|
|
</StackPanel>
|
|
|
|
<Grid ColumnDefinitions="*,16,*">
|
|
<StackPanel Grid.Column="0">
|
|
<TextBlock Classes="label" Text="Tagesbudget ($ USD)" />
|
|
<TextBox Text="{Binding InstanceDailyCostUsd}" />
|
|
</StackPanel>
|
|
<StackPanel Grid.Column="2">
|
|
<TextBlock Classes="label" Text="Tagesbudget (Tokens)" />
|
|
<TextBox Text="{Binding InstanceDailyTokens}" />
|
|
</StackPanel>
|
|
</Grid>
|
|
</StackPanel>
|
|
|
|
<Border Classes="hr" />
|
|
|
|
<!-- ══════════════════ Allgemein ══════════════════ -->
|
|
<StackPanel Spacing="14">
|
|
<TextBlock Classes="kicker" Text="ALLGEMEIN" />
|
|
|
|
<StackPanel>
|
|
<TextBlock Classes="label" Text="Instanzen-Verzeichnis" />
|
|
<TextBox Text="{Binding InstancesDirectory}" />
|
|
</StackPanel>
|
|
|
|
<Grid ColumnDefinitions="*,16,*">
|
|
<StackPanel Grid.Column="0">
|
|
<TextBlock Classes="label" Text="Minimaler Log-Level" />
|
|
<ComboBox ItemsSource="{Binding LogLevels}" SelectedItem="{Binding MinimumLogLevel}"
|
|
HorizontalAlignment="Stretch" />
|
|
</StackPanel>
|
|
<StackPanel Grid.Column="2">
|
|
<TextBlock Classes="label" Text="OpenRouter Base-URL" />
|
|
<TextBox Text="{Binding OpenRouterBaseUrl}" />
|
|
</StackPanel>
|
|
</Grid>
|
|
</StackPanel>
|
|
|
|
<Border Classes="hr" />
|
|
|
|
<!-- ══════════════════ Deploymentcenter ══════════════════ -->
|
|
<StackPanel Spacing="14">
|
|
<TextBlock Classes="kicker" Text="DEPLOYMENTCENTER & LIZENZ" />
|
|
|
|
<StackPanel>
|
|
<TextBlock Classes="label" Text="Server-URL" />
|
|
<TextBox Text="{Binding DeploymentcenterUrl}" />
|
|
</StackPanel>
|
|
|
|
<StackPanel>
|
|
<TextBlock Classes="label" Text="Master-Token" />
|
|
<TextBox Text="{Binding DeploymentcenterToken}" PasswordChar="•" />
|
|
</StackPanel>
|
|
|
|
<Grid ColumnDefinitions="*,16,*">
|
|
<StackPanel Grid.Column="0">
|
|
<TextBlock Classes="label" Text="Update-Kanal" />
|
|
<ComboBox ItemsSource="{Binding UpdateChannels}" SelectedItem="{Binding UpdateChannel}"
|
|
HorizontalAlignment="Stretch" />
|
|
</StackPanel>
|
|
<StackPanel Grid.Column="2">
|
|
<TextBlock Classes="label" Text="Umgebung" />
|
|
<ComboBox ItemsSource="{Binding Environments}"
|
|
SelectedItem="{Binding DeploymentcenterEnvironment}"
|
|
HorizontalAlignment="Stretch" />
|
|
</StackPanel>
|
|
</Grid>
|
|
|
|
<StackPanel>
|
|
<TextBlock Classes="label" Text="Lizenzschlüssel" />
|
|
<TextBox Text="{Binding LicenseKey}" PasswordChar="•" />
|
|
</StackPanel>
|
|
|
|
<StackPanel Spacing="10" Margin="0,4,0,0">
|
|
<CheckBox Content="Fehler automatisch an Deploymentcenter melden"
|
|
IsChecked="{Binding ErrorReportingEnabled}" />
|
|
<CheckBox Content="Beim Start automatisch auf Updates prüfen"
|
|
IsChecked="{Binding UpdateCheckEnabled}" />
|
|
</StackPanel>
|
|
</StackPanel>
|
|
|
|
</StackPanel>
|
|
</ScrollViewer>
|
|
|
|
</DockPanel>
|
|
|
|
</UserControl>
|