feat(ui): Throttle-Stufen im Ausfuehrung-Tab sichtbar machen
Die vier UsageThrottle-Prozente waren nur per Gauge-Drag im Usage-Monitor erreichbar und wurden im Settings-Modal unsichtbar durchgeschleift. Jetzt read-only angezeigt plus Button in den Usage-Monitor. Der Button schliesst die Settings absichtlich: Save() schreibt die beim Oeffnen gelesenen Throttle-Werte zurueck und wuerde ein zwischenzeitliches Draggen ueberschreiben.
This commit is contained in:
@@ -40,6 +40,10 @@
|
|||||||
"usageGateSevenDayPct": "7-Tage-Fenster (%)",
|
"usageGateSevenDayPct": "7-Tage-Fenster (%)",
|
||||||
"autoContinueOnUsageLimit": "Nach Limit-Reset fortsetzen",
|
"autoContinueOnUsageLimit": "Nach Limit-Reset fortsetzen",
|
||||||
"autoContinueOnUsageLimitHint": "Ist ein Run am Nutzungslimit abgebrochen, wird er nach Ablauf des 5-Stunden-Fensters automatisch fortgesetzt. Weckt außerdem die pausierte Queue genau zum Reset-Zeitpunkt statt erst beim nächsten Backstop-Check.",
|
"autoContinueOnUsageLimitHint": "Ist ein Run am Nutzungslimit abgebrochen, wird er nach Ablauf des 5-Stunden-Fensters automatisch fortgesetzt. Weckt außerdem die pausierte Queue genau zum Reset-Zeitpunkt statt erst beim nächsten Backstop-Check.",
|
||||||
|
"throttleStagesHeading": "Throttle-Stufen",
|
||||||
|
"throttleStagesHint": "Die Parallelität wird vor dem harten Gate begrenzt: soft auf 2 Slots, hard auf 1. Eingestellt wird das durch Ziehen der Marker an den Gauges im Usage-Monitor. Der Monitor schließt diese Einstellungen — vorher speichern, wenn du etwas geändert hast.",
|
||||||
|
"throttleStagesValues": "5h: soft {0}% / hard {1}% · 7d: soft {2}% / hard {3}%",
|
||||||
|
"openUsageMonitor": "Usage-Monitor öffnen...",
|
||||||
"reportExcludedPaths": "Bericht: ausgeschlossene Pfade (einer pro Zeile)",
|
"reportExcludedPaths": "Bericht: ausgeschlossene Pfade (einer pro Zeile)",
|
||||||
"standupWeekday": "Standup-Wochentag",
|
"standupWeekday": "Standup-Wochentag",
|
||||||
"weekdaySunday": "Sonntag",
|
"weekdaySunday": "Sonntag",
|
||||||
@@ -66,6 +70,10 @@
|
|||||||
"confirmRemoveAll": "ALLE Worktrees entfernen? Nicht committete Arbeit geht verloren."
|
"confirmRemoveAll": "ALLE Worktrees entfernen? Nicht committete Arbeit geht verloren."
|
||||||
},
|
},
|
||||||
"files": {
|
"files": {
|
||||||
|
"cliSection": "CLAUDE CLI",
|
||||||
|
"claudeBinHint": "Befehl oder vollständiger Pfad, den der Worker startet. Leer setzt auf \"claude\" zurück. Gilt ab dem nächsten Task-Run — kein Neustart nötig.",
|
||||||
|
"claudeBinResolved": "Aufgelöst zu: {0}",
|
||||||
|
"claudeBinUnresolved": "Nicht im PATH gefunden — Task-Runs schlagen fehl, solange das so bleibt.",
|
||||||
"agentsSection": "AGENTEN",
|
"agentsSection": "AGENTEN",
|
||||||
"agentsHint": "Mitgelieferte Standard-Agenten wiederherstellen. Vorhandene Dateien werden nicht überschrieben.",
|
"agentsHint": "Mitgelieferte Standard-Agenten wiederherstellen. Vorhandene Dateien werden nicht überschrieben.",
|
||||||
"restoreDefaultAgents": "Standard-Agenten wiederherstellen",
|
"restoreDefaultAgents": "Standard-Agenten wiederherstellen",
|
||||||
@@ -762,6 +770,9 @@
|
|||||||
"forceRemoving": "Worktree wird zwangsweise entfernt…",
|
"forceRemoving": "Worktree wird zwangsweise entfernt…",
|
||||||
"batchMerging": "Merge {0}/{1}…"
|
"batchMerging": "Merge {0}/{1}…"
|
||||||
},
|
},
|
||||||
|
"claudeBin": {
|
||||||
|
"saving": "claude_bin wird gespeichert…"
|
||||||
|
},
|
||||||
"skills": {
|
"skills": {
|
||||||
"installing": "Skill wird geklont…",
|
"installing": "Skill wird geklont…",
|
||||||
"updating": "Skill wird aktualisiert…",
|
"updating": "Skill wird aktualisiert…",
|
||||||
|
|||||||
@@ -40,6 +40,10 @@
|
|||||||
"usageGateSevenDayPct": "7-day window (%)",
|
"usageGateSevenDayPct": "7-day window (%)",
|
||||||
"autoContinueOnUsageLimit": "Continue on session limit reset",
|
"autoContinueOnUsageLimit": "Continue on session limit reset",
|
||||||
"autoContinueOnUsageLimitHint": "When a run stops because it hit the usage limit, automatically continue it once the 5-hour window resets. Also wakes the paused queue exactly at reset time instead of waiting for the next backstop check.",
|
"autoContinueOnUsageLimitHint": "When a run stops because it hit the usage limit, automatically continue it once the 5-hour window resets. Also wakes the paused queue exactly at reset time instead of waiting for the next backstop check.",
|
||||||
|
"throttleStagesHeading": "Throttle stages",
|
||||||
|
"throttleStagesHint": "Parallelism is capped before the hard gate: soft caps at 2 slots, hard at 1. Edited by dragging the markers on the usage-monitor gauges. Opening the monitor closes these settings — save first if you changed anything.",
|
||||||
|
"throttleStagesValues": "5h: soft {0}% / hard {1}% · 7d: soft {2}% / hard {3}%",
|
||||||
|
"openUsageMonitor": "Open usage monitor...",
|
||||||
"reportExcludedPaths": "Report: excluded paths (one per line)",
|
"reportExcludedPaths": "Report: excluded paths (one per line)",
|
||||||
"standupWeekday": "Standup weekday",
|
"standupWeekday": "Standup weekday",
|
||||||
"weekdaySunday": "Sunday",
|
"weekdaySunday": "Sunday",
|
||||||
@@ -66,6 +70,10 @@
|
|||||||
"confirmRemoveAll": "Remove ALL worktrees? Uncommitted work will be lost."
|
"confirmRemoveAll": "Remove ALL worktrees? Uncommitted work will be lost."
|
||||||
},
|
},
|
||||||
"files": {
|
"files": {
|
||||||
|
"cliSection": "CLAUDE CLI",
|
||||||
|
"claudeBinHint": "Command or full path the worker starts. Blank resets to \"claude\". Applies to the next task run — no restart needed.",
|
||||||
|
"claudeBinResolved": "Resolves to: {0}",
|
||||||
|
"claudeBinUnresolved": "Not found on PATH — task runs will fail until this resolves.",
|
||||||
"agentsSection": "AGENTS",
|
"agentsSection": "AGENTS",
|
||||||
"agentsHint": "Restore bundled default agents. Existing files are not overwritten.",
|
"agentsHint": "Restore bundled default agents. Existing files are not overwritten.",
|
||||||
"restoreDefaultAgents": "Restore default agents",
|
"restoreDefaultAgents": "Restore default agents",
|
||||||
@@ -762,6 +770,9 @@
|
|||||||
"forceRemoving": "Force-removing worktree…",
|
"forceRemoving": "Force-removing worktree…",
|
||||||
"batchMerging": "Merging {0}/{1}…"
|
"batchMerging": "Merging {0}/{1}…"
|
||||||
},
|
},
|
||||||
|
"claudeBin": {
|
||||||
|
"saving": "Saving claude_bin…"
|
||||||
|
},
|
||||||
"skills": {
|
"skills": {
|
||||||
"installing": "Cloning skill…",
|
"installing": "Cloning skill…",
|
||||||
"updating": "Updating skill…",
|
"updating": "Updating skill…",
|
||||||
|
|||||||
@@ -66,6 +66,18 @@ public sealed partial class SettingsModalViewModel : ViewModelBase
|
|||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private void OpenRepoImport() => RequestRepoImport?.Invoke();
|
private void OpenRepoImport() => RequestRepoImport?.Invoke();
|
||||||
|
|
||||||
|
// Same deal for the usage monitor, which owns the throttle-stage editor. It must *close* this
|
||||||
|
// modal rather than stack on top: Save() writes the throttle values it read at open, so a drag
|
||||||
|
// made while Settings is still open would be overwritten on save.
|
||||||
|
public Action? RequestUsageMonitor { get; set; }
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void OpenUsageMonitor() => RequestUsageMonitor?.Invoke();
|
||||||
|
|
||||||
|
/// Read-only echo of the four throttle percentages, which are edited by dragging the
|
||||||
|
/// usage-monitor gauges — without this the Execution tab silently carries them through.
|
||||||
|
[ObservableProperty] private string _throttleSummary = "";
|
||||||
|
|
||||||
[ObservableProperty] private string _validationError = "";
|
[ObservableProperty] private string _validationError = "";
|
||||||
[ObservableProperty] private bool _isBusy;
|
[ObservableProperty] private bool _isBusy;
|
||||||
[ObservableProperty] private string _statusMessage = "";
|
[ObservableProperty] private string _statusMessage = "";
|
||||||
@@ -135,6 +147,9 @@ public sealed partial class SettingsModalViewModel : ViewModelBase
|
|||||||
_throttleStages = (
|
_throttleStages = (
|
||||||
dto.UsageThrottleFiveHourSoftPct, dto.UsageThrottleFiveHourHardPct,
|
dto.UsageThrottleFiveHourSoftPct, dto.UsageThrottleFiveHourHardPct,
|
||||||
dto.UsageThrottleSevenDaySoftPct, dto.UsageThrottleSevenDayHardPct);
|
dto.UsageThrottleSevenDaySoftPct, dto.UsageThrottleSevenDayHardPct);
|
||||||
|
ThrottleSummary = Loc.T("settings.general.throttleStagesValues",
|
||||||
|
_throttleStages.FiveSoft, _throttleStages.FiveHard,
|
||||||
|
_throttleStages.SevenSoft, _throttleStages.SevenHard);
|
||||||
Worktrees.WorktreeStrategy = dto.WorktreeStrategy ?? "sibling";
|
Worktrees.WorktreeStrategy = dto.WorktreeStrategy ?? "sibling";
|
||||||
Worktrees.CentralWorktreeRoot = dto.CentralWorktreeRoot;
|
Worktrees.CentralWorktreeRoot = dto.CentralWorktreeRoot;
|
||||||
Worktrees.WorktreeAutoCleanupEnabled = dto.WorktreeAutoCleanupEnabled;
|
Worktrees.WorktreeAutoCleanupEnabled = dto.WorktreeAutoCleanupEnabled;
|
||||||
@@ -148,6 +163,7 @@ public sealed partial class SettingsModalViewModel : ViewModelBase
|
|||||||
}
|
}
|
||||||
else StatusMessage = Loc.T("vm.settingsModal.workerOffline");
|
else StatusMessage = Loc.T("vm.settingsModal.workerOffline");
|
||||||
|
|
||||||
|
await Files.LoadClaudeBinAsync();
|
||||||
await Prime.LoadAsync();
|
await Prime.LoadAsync();
|
||||||
await OnlineInbox.LoadAsync();
|
await OnlineInbox.LoadAsync();
|
||||||
await SessionSkills.LoadAsync(dto?.SessionSkills);
|
await SessionSkills.LoadAsync(dto?.SessionSkills);
|
||||||
|
|||||||
@@ -252,6 +252,18 @@
|
|||||||
<TextBlock Text="{loc:Tr settings.general.autoContinueOnUsageLimitHint}"
|
<TextBlock Text="{loc:Tr settings.general.autoContinueOnUsageLimitHint}"
|
||||||
Opacity="0.6" FontSize="12" TextWrapping="Wrap"/>
|
Opacity="0.6" FontSize="12" TextWrapping="Wrap"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
|
<!-- Throttle stages live on the usage-monitor gauges (drag + spinner per stage);
|
||||||
|
echoed read-only here so they aren't invisible on the tab that owns the gate. -->
|
||||||
|
<StackPanel Spacing="4">
|
||||||
|
<TextBlock Classes="field-label" Text="{loc:Tr settings.general.throttleStagesHeading}"/>
|
||||||
|
<TextBlock Text="{Binding ThrottleSummary}" Classes="meta"/>
|
||||||
|
<TextBlock Text="{loc:Tr settings.general.throttleStagesHint}"
|
||||||
|
Opacity="0.6" FontSize="12" TextWrapping="Wrap"/>
|
||||||
|
<Button Classes="btn" HorizontalAlignment="Left"
|
||||||
|
Content="{loc:Tr settings.general.openUsageMonitor}"
|
||||||
|
Command="{Binding OpenUsageMonitorCommand}"/>
|
||||||
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</TabItem>
|
</TabItem>
|
||||||
@@ -394,6 +406,22 @@
|
|||||||
<TabItem Header="{loc:Tr settings.sidebar.categoryFiles}">
|
<TabItem Header="{loc:Tr settings.sidebar.categoryFiles}">
|
||||||
<ScrollViewer>
|
<ScrollViewer>
|
||||||
<StackPanel Spacing="12" Margin="0,8,0,0">
|
<StackPanel Spacing="12" Margin="0,8,0,0">
|
||||||
|
<!-- claude_bin from worker.config.json — saved on its own button, not the modal's
|
||||||
|
Save, because the worker owns that file rather than app_settings. -->
|
||||||
|
<StackPanel Spacing="6">
|
||||||
|
<TextBlock Classes="section-label" Text="{loc:Tr settings.files.cliSection}"/>
|
||||||
|
<TextBlock Classes="meta" Text="{loc:Tr settings.files.claudeBinHint}" TextWrapping="Wrap"/>
|
||||||
|
<Grid ColumnDefinitions="*,Auto" ColumnSpacing="8">
|
||||||
|
<TextBox Grid.Column="0" Text="{Binding Files.ClaudeBin, Mode=TwoWay}"
|
||||||
|
PlaceholderText="claude"/>
|
||||||
|
<Button Grid.Column="1" Classes="btn" Content="{loc:Tr settings.save}"
|
||||||
|
Command="{Binding Files.SaveClaudeBinCommand}"/>
|
||||||
|
</Grid>
|
||||||
|
<ctl:OperationIndicator Status="{Binding Files.ClaudeBinOp}"/>
|
||||||
|
<TextBlock Classes="path-mono" TextWrapping="Wrap"
|
||||||
|
Text="{Binding Files.ClaudeBinResolvedHint}"
|
||||||
|
IsVisible="{Binding Files.ClaudeBinResolvedHint, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||||
|
</StackPanel>
|
||||||
<StackPanel Spacing="6">
|
<StackPanel Spacing="6">
|
||||||
<TextBlock Classes="section-label" Text="{loc:Tr settings.files.agentsSection}"/>
|
<TextBlock Classes="section-label" Text="{loc:Tr settings.files.agentsSection}"/>
|
||||||
<TextBlock Classes="meta" Text="{loc:Tr settings.files.agentsHint}"
|
<TextBlock Classes="meta" Text="{loc:Tr settings.files.agentsHint}"
|
||||||
|
|||||||
@@ -77,6 +77,11 @@ public sealed class WindowDialogService : IDialogService
|
|||||||
dlg.Close();
|
dlg.Close();
|
||||||
if (Shell is not null) _ = Shell.OpenRepoImportCommand.ExecuteAsync(null);
|
if (Shell is not null) _ = Shell.OpenRepoImportCommand.ExecuteAsync(null);
|
||||||
};
|
};
|
||||||
|
vm.RequestUsageMonitor = () =>
|
||||||
|
{
|
||||||
|
dlg.Close();
|
||||||
|
if (Shell is not null) _ = Shell.OpenUsageMonitorCommand.ExecuteAsync(null);
|
||||||
|
};
|
||||||
await dlg.ShowDialog(ActiveOwner());
|
await dlg.ShowDialog(ActiveOwner());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user