feat(ui): add config override fields to TaskEditorView

Adds Model, SystemPrompt, and AgentPath override fields to TaskEditorViewModel and TaskEditorView. Wires agent loading from WorkerClient in TaskListViewModel before opening the editor dialog.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Mika Kuns
2026-04-14 16:39:50 +02:00
parent 699fe8a148
commit f8be2c178b
3 changed files with 58 additions and 1 deletions

View File

@@ -1,4 +1,5 @@
using ClaudeDo.Data.Models; using ClaudeDo.Data.Models;
using ClaudeDo.Ui.Services;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using TaskStatus = ClaudeDo.Data.Models.TaskStatus; using TaskStatus = ClaudeDo.Data.Models.TaskStatus;
@@ -13,6 +14,10 @@ public partial class TaskEditorViewModel : ViewModelBase
[ObservableProperty] private string _statusChoice = "manual"; [ObservableProperty] private string _statusChoice = "manual";
[ObservableProperty] private string _tagsInput = ""; [ObservableProperty] private string _tagsInput = "";
[ObservableProperty] private string _windowTitle = "New Task"; [ObservableProperty] private string _windowTitle = "New Task";
[ObservableProperty] private string _modelChoice = "(list default)";
[ObservableProperty] private string? _systemPromptOverride;
[ObservableProperty] private AgentInfo? _selectedAgent;
public List<AgentInfo> AvailableAgents { get; set; } = [];
private string? _editId; private string? _editId;
private string _listId = ""; private string _listId = "";
@@ -21,12 +26,19 @@ public partial class TaskEditorViewModel : ViewModelBase
public event Action? RequestClose; public event Action? RequestClose;
public static string[] ModelChoices { get; } = ["(list default)", "Sonnet", "Opus", "Haiku"];
public static string[] CommitTypes { get; } = public static string[] CommitTypes { get; } =
["chore", "feat", "fix", "refactor", "docs", "test", "perf", "style", "build", "ci"]; ["chore", "feat", "fix", "refactor", "docs", "test", "perf", "style", "build", "ci"];
public static string[] StatusChoices { get; } = public static string[] StatusChoices { get; } =
["manual", "queued"]; ["manual", "queued"];
public async Task LoadAgentsAsync(WorkerClient worker)
{
AvailableAgents = await worker.GetAgentsAsync();
}
public IReadOnlyList<string> SelectedTagNames => public IReadOnlyList<string> SelectedTagNames =>
TagsInput.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) TagsInput.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
.Distinct() .Distinct()
@@ -56,6 +68,13 @@ public partial class TaskEditorViewModel : ViewModelBase
_ => entity.Status.ToString().ToLowerInvariant(), _ => entity.Status.ToString().ToLowerInvariant(),
}; };
TagsInput = string.Join(", ", taskTags.Select(t => t.Name)); TagsInput = string.Join(", ", taskTags.Select(t => t.Name));
ModelChoice = entity.Model is not null
? ListEditorViewModel.ModelIdToDisplay(entity.Model)
: "(list default)";
SystemPromptOverride = entity.SystemPrompt;
SelectedAgent = entity.AgentPath is not null
? AvailableAgents.FirstOrDefault(a => a.Path == entity.AgentPath)
: null;
WindowTitle = $"Edit Task: {entity.Title}"; WindowTitle = $"Edit Task: {entity.Title}";
} }
@@ -78,6 +97,11 @@ public partial class TaskEditorViewModel : ViewModelBase
CommitType = CommitType, CommitType = CommitType,
CreatedAt = _createdAt, CreatedAt = _createdAt,
}; };
entity.Model = ModelChoice != "(list default)"
? ListEditorViewModel.ModelDisplayToId(ModelChoice)
: null;
entity.SystemPrompt = string.IsNullOrWhiteSpace(SystemPromptOverride) ? null : SystemPromptOverride.Trim();
entity.AgentPath = SelectedAgent?.Path;
_tcs.TrySetResult(entity); _tcs.TrySetResult(entity);
RequestClose?.Invoke(); RequestClose?.Invoke();
} }

View File

@@ -146,6 +146,7 @@ public partial class TaskListViewModel : ViewModelBase
var defaultCommitType = list?.DefaultCommitType ?? "chore"; var defaultCommitType = list?.DefaultCommitType ?? "chore";
var editor = _editorFactory(); var editor = _editorFactory();
await editor.LoadAgentsAsync(_worker);
editor.InitForCreate(CurrentListId, defaultCommitType); editor.InitForCreate(CurrentListId, defaultCommitType);
var window = new TaskEditorView { DataContext = editor }; var window = new TaskEditorView { DataContext = editor };
@@ -191,6 +192,7 @@ public partial class TaskListViewModel : ViewModelBase
var taskTags = await _taskRepo.GetTagsAsync(entity.Id); var taskTags = await _taskRepo.GetTagsAsync(entity.Id);
var editor = _editorFactory(); var editor = _editorFactory();
await editor.LoadAgentsAsync(_worker);
editor.InitForEdit(entity, taskTags); editor.InitForEdit(entity, taskTags);
var window = new TaskEditorView { DataContext = editor }; var window = new TaskEditorView { DataContext = editor };

View File

@@ -1,10 +1,11 @@
<Window xmlns="https://github.com/avaloniaui" <Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:ClaudeDo.Ui.ViewModels" xmlns:vm="using:ClaudeDo.Ui.ViewModels"
xmlns:models="using:ClaudeDo.Data.Models"
x:Class="ClaudeDo.Ui.Views.TaskEditorView" x:Class="ClaudeDo.Ui.Views.TaskEditorView"
x:DataType="vm:TaskEditorViewModel" x:DataType="vm:TaskEditorViewModel"
Title="{Binding WindowTitle}" Title="{Binding WindowTitle}"
Width="500" Height="420" Width="500" Height="600"
WindowStartupLocation="CenterOwner" WindowStartupLocation="CenterOwner"
CanResize="False" CanResize="False"
Background="{StaticResource WindowBgBrush}"> Background="{StaticResource WindowBgBrush}">
@@ -34,6 +35,36 @@
<TextBlock Text="Tags (comma-separated)" FontWeight="SemiBold" Foreground="{StaticResource TextSecondaryBrush}"/> <TextBlock Text="Tags (comma-separated)" FontWeight="SemiBold" Foreground="{StaticResource TextSecondaryBrush}"/>
<TextBox Text="{Binding TagsInput}" PlaceholderText="agent, manual, code, ..."/> <TextBox Text="{Binding TagsInput}" PlaceholderText="agent, manual, code, ..."/>
<!-- Divider -->
<Border Height="1" Background="{StaticResource BorderSubtleBrush}" Margin="0,6,0,2"/>
<TextBlock Text="Agent Config (overrides)" FontWeight="Bold" FontSize="13"
Foreground="{StaticResource TextPrimaryBrush}"/>
<TextBlock Text="Model" FontWeight="SemiBold"
Foreground="{StaticResource TextSecondaryBrush}"/>
<ComboBox ItemsSource="{Binding ModelChoices}"
SelectedItem="{Binding ModelChoice}"
MinWidth="150"/>
<TextBlock Text="System Prompt" FontWeight="SemiBold"
Foreground="{StaticResource TextSecondaryBrush}"/>
<TextBox Text="{Binding SystemPromptOverride}"
PlaceholderText="(inherits from list)"
AcceptsReturn="True" TextWrapping="Wrap" MinHeight="50"/>
<TextBlock Text="Agent File" FontWeight="SemiBold"
Foreground="{StaticResource TextSecondaryBrush}"/>
<ComboBox ItemsSource="{Binding AvailableAgents}"
SelectedItem="{Binding SelectedAgent}"
MinWidth="150">
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="models:AgentInfo">
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<StackPanel Orientation="Horizontal" Spacing="8" HorizontalAlignment="Right" Margin="0,10,0,0"> <StackPanel Orientation="Horizontal" Spacing="8" HorizontalAlignment="Right" Margin="0,10,0,0">
<Button Content="Save" Command="{Binding SaveCommand}" IsDefault="True" MinWidth="80" <Button Content="Save" Command="{Binding SaveCommand}" IsDefault="True" MinWidth="80"
Background="{StaticResource AccentBrush}" Foreground="{StaticResource TextPrimaryBrush}"/> Background="{StaticResource AccentBrush}" Foreground="{StaticResource TextPrimaryBrush}"/>