refactor(agent-config): single AgentConfigEditor for list + task scopes

This commit is contained in:
Mika Kuns
2026-06-23 08:52:49 +02:00
parent 60eb671e8f
commit eb0ddb56d3
14 changed files with 761 additions and 482 deletions

View File

@@ -4,6 +4,7 @@ using ClaudeDo.Data.Models;
using ClaudeDo.Data.Repositories;
using ClaudeDo.Ui.Localization;
using ClaudeDo.Ui.Services;
using ClaudeDo.Ui.ViewModels.Agent;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.EntityFrameworkCore;
@@ -28,25 +29,11 @@ public sealed partial class ListSettingsModalViewModel : ViewModelBase
[ObservableProperty] private string _workingDir = "";
[ObservableProperty] private string _defaultCommitType = CommitTypeRegistry.DefaultType;
[ObservableProperty] private string? _selectedModel; // null = inherit from global
[ObservableProperty] private decimal? _maxTurns; // null = inherit from global
[ObservableProperty] private string _modelInheritedHint = ""; // resolved value placeholder, e.g. "sonnet"
[ObservableProperty] private string _modelBadge = "";
[ObservableProperty] private string _turnsInheritedHint = "";
[ObservableProperty] private string _turnsBadge = "";
[ObservableProperty] private string _agentBadge = "";
[ObservableProperty] private string _systemPrompt = "";
[ObservableProperty] private AgentInfo? _selectedAgent;
private string _globalModel = ModelRegistry.DefaultAlias;
private int _globalMaxTurns = 100;
public ObservableCollection<string> ModelOptions { get; } = new(ModelRegistry.Aliases);
public ObservableCollection<string> CommitTypeOptions { get; } = new(CommitTypeRegistry.Types);
public ObservableCollection<AgentInfo> Agents { get; } = new();
// The shared agent-config editor (Model / MaxTurns / SystemPrompt / AgentFile),
// scoped to this list (list → global inheritance).
public AgentConfigEditorViewModel Agent { get; }
public Action? CloseAction { get; set; }
@@ -54,34 +41,7 @@ public sealed partial class ListSettingsModalViewModel : ViewModelBase
{
_worker = worker;
_dbFactory = dbFactory;
}
partial void OnSelectedModelChanged(string? value) => RecomputeModelBadge();
partial void OnMaxTurnsChanged(decimal? value) => RecomputeTurnsBadge();
partial void OnSelectedAgentChanged(AgentInfo? value) => RecomputeAgentBadge();
private void RecomputeModelBadge()
{
ModelInheritedHint = _globalModel;
ModelBadge = !string.IsNullOrWhiteSpace(SelectedModel)
? Loc.T("settings.inherit.overrideBadge")
: Loc.T("settings.inherit.inheritedFromGlobal");
}
private void RecomputeTurnsBadge()
{
TurnsInheritedHint = _globalMaxTurns.ToString();
TurnsBadge = MaxTurns is not null
? Loc.T("settings.inherit.overrideBadge")
: Loc.T("settings.inherit.inheritedFromGlobal");
}
private void RecomputeAgentBadge()
{
var overridden = SelectedAgent is not null && !string.IsNullOrWhiteSpace(SelectedAgent.Path);
AgentBadge = overridden
? Loc.T("settings.inherit.overrideBadge")
: Loc.T("settings.inherit.inheritedFromGlobal");
Agent = new AgentConfigEditorViewModel(worker, AgentConfigScope.List);
}
public async Task LoadAsync(
@@ -96,44 +56,19 @@ public sealed partial class ListSettingsModalViewModel : ViewModelBase
WorkingDir = workingDir ?? "";
DefaultCommitType = string.IsNullOrWhiteSpace(defaultCommitType) ? CommitTypeRegistry.DefaultType : defaultCommitType;
Agents.Clear();
Agents.Add(new AgentInfo("(none)", "", ""));
var agents = await _worker.GetAgentsAsync();
foreach (var a in agents) Agents.Add(a);
var config = await _worker.GetListConfigAsync(listId);
var app = await _worker.GetAppSettingsAsync();
_globalModel = app?.DefaultModel ?? ModelRegistry.DefaultAlias;
_globalMaxTurns = app?.DefaultMaxTurns ?? 100;
SelectedModel = string.IsNullOrWhiteSpace(config?.Model) ? null : config!.Model!;
MaxTurns = config?.MaxTurns is int mt ? mt : (decimal?)null;
SystemPrompt = config?.SystemPrompt ?? "";
SelectedAgent = string.IsNullOrWhiteSpace(config?.AgentPath)
? Agents[0]
: (Agents.FirstOrDefault(a => a.Path == config!.AgentPath) ?? Agents[0]);
RecomputeModelBadge();
RecomputeTurnsBadge();
RecomputeAgentBadge();
await Agent.LoadForListAsync(listId, ct);
}
[RelayCommand]
private async Task SaveAsync()
{
var model = string.IsNullOrWhiteSpace(SelectedModel) ? null : SelectedModel;
var sp = string.IsNullOrWhiteSpace(SystemPrompt) ? null : SystemPrompt;
var ap = SelectedAgent is null || string.IsNullOrWhiteSpace(SelectedAgent.Path) ? null : SelectedAgent.Path;
var turns = MaxTurns is decimal d ? (int?)d : null;
await _worker.UpdateListAsync(new UpdateListDto(
ListId,
string.IsNullOrWhiteSpace(Name) ? Loc.T("vm.listSettings.untitled") : Name,
string.IsNullOrWhiteSpace(WorkingDir) ? null : WorkingDir,
DefaultCommitType));
await _worker.UpdateListConfigAsync(new UpdateListConfigDto(ListId, model, sp, ap, turns));
await Agent.SaveAsync();
CloseAction?.Invoke();
}
@@ -171,17 +106,4 @@ public sealed partial class ListSettingsModalViewModel : ViewModelBase
[RelayCommand]
private void Cancel() => CloseAction?.Invoke();
[RelayCommand] private void ResetModel() => SelectedModel = null;
[RelayCommand] private void ResetTurns() => MaxTurns = null;
[RelayCommand] private void ResetAgent() => SelectedAgent = Agents.Count > 0 ? Agents[0] : null;
[RelayCommand]
private void ResetAgentSettings()
{
SelectedModel = null;
MaxTurns = null;
SystemPrompt = "";
SelectedAgent = Agents.Count > 0 ? Agents[0] : null;
}
}