using ClaudeDo.Data.Models; using ClaudeDo.Ui.Services; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using TaskStatus = ClaudeDo.Data.Models.TaskStatus; namespace ClaudeDo.Ui.ViewModels; public partial class TaskEditorViewModel : ViewModelBase { [ObservableProperty] private string _title = ""; [ObservableProperty] private string? _description; [ObservableProperty] private string _commitType = "chore"; [ObservableProperty] private string _statusChoice = "manual"; [ObservableProperty] private string _tagsInput = ""; [ObservableProperty] private string _windowTitle = "New Task"; [ObservableProperty] private string _modelChoice = "(list default)"; [ObservableProperty] private string? _systemPromptOverride; [ObservableProperty] private AgentInfo? _selectedAgent; public List AvailableAgents { get; set; } = []; private string? _editId; private string _listId = ""; private DateTime _createdAt; private TaskCompletionSource _tcs = new(); public event Action? RequestClose; public static string[] ModelChoices { get; } = ["(list default)", "Sonnet", "Opus", "Haiku"]; public static string[] CommitTypes { get; } = ["chore", "feat", "fix", "refactor", "docs", "test", "perf", "style", "build", "ci"]; public static string[] StatusChoices { get; } = ["manual", "queued"]; public async Task LoadAgentsAsync(WorkerClient worker) { AvailableAgents = await worker.GetAgentsAsync(); } public IReadOnlyList SelectedTagNames => TagsInput.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) .Distinct() .ToList(); public void InitForCreate(string listId, string defaultCommitType = "chore") { _editId = null; _listId = listId; _createdAt = DateTime.UtcNow; CommitType = defaultCommitType; WindowTitle = "New Task"; } public void InitForEdit(TaskEntity entity, IReadOnlyList taskTags) { _editId = entity.Id; _listId = entity.ListId; _createdAt = entity.CreatedAt; Title = entity.Title; Description = entity.Description; CommitType = entity.CommitType; StatusChoice = entity.Status switch { TaskStatus.Manual => "manual", TaskStatus.Queued => "queued", _ => entity.Status.ToString().ToLowerInvariant(), }; 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}"; } [RelayCommand] private void Save() { if (string.IsNullOrWhiteSpace(Title)) return; var status = StatusChoice switch { "queued" => TaskStatus.Queued, _ => TaskStatus.Manual, }; var entity = new TaskEntity { Id = _editId ?? Guid.NewGuid().ToString(), ListId = _listId, Title = Title.Trim(), Description = string.IsNullOrWhiteSpace(Description) ? null : Description.Trim(), Status = status, CommitType = CommitType, 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); RequestClose?.Invoke(); } [RelayCommand] private void Cancel() { _tcs.TrySetResult(null); RequestClose?.Invoke(); } public void OnWindowClosed() { _tcs.TrySetResult(null); } public Task ShowAndWaitAsync() { _tcs = new TaskCompletionSource(); return _tcs.Task; } }