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

@@ -0,0 +1,259 @@
using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using ClaudeDo.Data.Models;
using ClaudeDo.Ui.Localization;
using ClaudeDo.Ui.Services;
namespace ClaudeDo.Ui.ViewModels.Agent;
public enum AgentConfigScope { List, Task }
/// <summary>
/// One agent-config editor (Model / MaxTurns / SystemPrompt / AgentFile with inherited
/// badges + reset) shared by the List Settings modal and the per-task gear flyout.
/// Scope picks the inheritance depth (List: list→global; Task: task→list→global) and the
/// persistence (List: explicit <see cref="SaveAsync"/>; Task: debounced auto-save).
/// </summary>
public sealed partial class AgentConfigEditorViewModel : ViewModelBase, IDisposable
{
private readonly IWorkerClient _worker;
private readonly AgentConfigScope _scope;
private readonly EventHandler _langChangedHandler;
/// scope==List ⇒ the list id; scope==Task ⇒ the task id. Null ⇒ no save target.
internal string? TargetId { get; set; }
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(IsEnabled))]
private bool _isRunning;
// Task scope gates the editor while the run is live; List scope is always enabled.
public bool IsEnabled => !IsRunning;
[ObservableProperty] private string? _model;
[ObservableProperty] private decimal? _maxTurns;
[ObservableProperty] private string _systemPrompt = "";
[ObservableProperty] private AgentInfo? _selectedAgent;
[ObservableProperty] private string _modelBadge = "";
[ObservableProperty] private string _modelInheritedHint = "";
[ObservableProperty] private string _turnsBadge = "";
[ObservableProperty] private string _turnsInheritedHint = "";
[ObservableProperty] private string _agentBadge = "";
[ObservableProperty] private string _effectiveSystemPromptHint = "";
private string _globalModel = ModelRegistry.DefaultAlias;
private int _globalMaxTurns = 100;
private string? _listModel; // Task scope only
private int? _listMaxTurns; // Task scope only
private string? _listAgentName; // Task scope only
private bool _suppressSave;
private CancellationTokenSource? _saveCts;
public int EffectiveMaxTurns =>
MaxTurns is decimal t ? (int)t : (_listMaxTurns ?? _globalMaxTurns);
public ObservableCollection<string> ModelOptions { get; } = new(ModelRegistry.Aliases);
public ObservableCollection<AgentInfo> Agents { get; } = new();
public AgentConfigEditorViewModel(IWorkerClient worker, AgentConfigScope scope)
{
_worker = worker;
_scope = scope;
_langChangedHandler = (_, _) => RecomputeBadges();
// Only the long-lived Task editor needs live re-badging; the List editor is a
// short-lived modal recreated with the current language on each open.
if (scope == AgentConfigScope.Task)
Loc.LanguageChanged += _langChangedHandler;
}
public void Dispose() => Loc.LanguageChanged -= _langChangedHandler;
partial void OnModelChanged(string? value) { RecomputeModelBadge(); QueueSave(); }
partial void OnMaxTurnsChanged(decimal? value)
{
RecomputeTurnsBadge();
OnPropertyChanged(nameof(EffectiveMaxTurns));
QueueSave();
}
partial void OnSystemPromptChanged(string value) => QueueSave();
partial void OnSelectedAgentChanged(AgentInfo? value) { RecomputeAgentBadge(); QueueSave(); }
private void RecomputeBadges()
{
RecomputeModelBadge();
RecomputeTurnsBadge();
RecomputeAgentBadge();
}
private void RecomputeModelBadge()
{
var own = string.IsNullOrWhiteSpace(Model) ? null : Model;
var (value, source) = _scope == AgentConfigScope.Task
? InheritanceResolver.Resolve(own, _listModel, _globalModel)
: InheritanceResolver.ResolveList(own, _globalModel);
ModelInheritedHint = value;
ModelBadge = BadgeFor(source, own is not null);
}
private void RecomputeTurnsBadge()
{
var own = MaxTurns?.ToString();
var (value, source) = _scope == AgentConfigScope.Task
? InheritanceResolver.Resolve(own, _listMaxTurns?.ToString(), _globalMaxTurns.ToString())
: InheritanceResolver.ResolveList(own, _globalMaxTurns.ToString());
TurnsInheritedHint = value;
TurnsBadge = BadgeFor(source, MaxTurns is not null);
}
private void RecomputeAgentBadge()
{
var agentSet = SelectedAgent is not null && !string.IsNullOrWhiteSpace(SelectedAgent.Path);
var own = agentSet ? SelectedAgent!.Path : null;
var (_, source) = _scope == AgentConfigScope.Task
? InheritanceResolver.Resolve(own, _listAgentName, null)
: InheritanceResolver.ResolveList(own, null);
AgentBadge = BadgeFor(source, agentSet);
}
private static string BadgeFor(InheritSource source, bool isSet) => isSet
? Loc.T("settings.inherit.overrideBadge")
: source == InheritSource.List
? Loc.T("settings.inherit.inheritedFromList")
: Loc.T("settings.inherit.inheritedFromGlobal");
private void QueueSave()
{
// List scope persists on the modal Save button; only Task auto-saves.
if (_suppressSave || _scope != AgentConfigScope.Task || TargetId is null) return;
_saveCts?.Cancel();
_saveCts = new CancellationTokenSource();
_ = DebouncedSaveAsync(_saveCts.Token);
}
private async System.Threading.Tasks.Task DebouncedSaveAsync(CancellationToken ct)
{
try
{
await System.Threading.Tasks.Task.Delay(300, ct);
if (TargetId is null) return;
await SaveAsync();
}
catch (OperationCanceledException) { }
catch { }
}
public async System.Threading.Tasks.Task SaveAsync()
{
if (TargetId is null) return;
var model = string.IsNullOrWhiteSpace(Model) ? null : Model;
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;
if (_scope == AgentConfigScope.Task)
await _worker.UpdateTaskAgentSettingsAsync(new UpdateTaskAgentSettingsDto(TargetId, model, sp, ap, turns));
else
await _worker.UpdateListConfigAsync(new UpdateListConfigDto(TargetId, model, sp, ap, turns));
}
public async System.Threading.Tasks.Task LoadForListAsync(string listId, CancellationToken ct = default)
{
_suppressSave = true;
try
{
TargetId = listId;
await ReloadAgentsAsync("(none)");
await LoadGlobalDefaultsAsync();
var cfg = await _worker.GetListConfigAsync(listId);
ApplyConfig(cfg?.Model, cfg?.MaxTurns, cfg?.SystemPrompt, cfg?.AgentPath);
_listModel = null; _listMaxTurns = null; _listAgentName = null;
EffectiveSystemPromptHint = "";
RecomputeBadges();
OnPropertyChanged(nameof(EffectiveMaxTurns));
}
finally { _suppressSave = false; }
}
public async System.Threading.Tasks.Task LoadForTaskAsync(TaskEntity entity, CancellationToken ct = default)
{
_suppressSave = true;
try
{
TargetId = entity.Id;
await ReloadAgentsAsync("(inherited)");
ApplyConfig(entity.Model, entity.MaxTurns, entity.SystemPrompt, entity.AgentPath);
var listCfg = await _worker.GetListConfigAsync(entity.ListId);
await LoadGlobalDefaultsAsync();
_listModel = listCfg?.Model;
_listMaxTurns = listCfg?.MaxTurns;
_listAgentName = string.IsNullOrWhiteSpace(listCfg?.AgentPath)
? null : System.IO.Path.GetFileName(listCfg!.AgentPath!);
EffectiveSystemPromptHint = string.IsNullOrWhiteSpace(listCfg?.SystemPrompt)
? "" : listCfg!.SystemPrompt!;
RecomputeBadges();
OnPropertyChanged(nameof(EffectiveMaxTurns));
}
finally { _suppressSave = false; }
}
public void Clear()
{
_suppressSave = true;
try
{
Model = null;
MaxTurns = null;
SystemPrompt = "";
SelectedAgent = null;
}
finally { _suppressSave = false; }
EffectiveSystemPromptHint = "";
TargetId = null;
}
private async System.Threading.Tasks.Task ReloadAgentsAsync(string placeholderName)
{
Agents.Clear();
Agents.Add(new AgentInfo(placeholderName, "", ""));
foreach (var a in await _worker.GetAgentsAsync()) Agents.Add(a);
}
private async System.Threading.Tasks.Task LoadGlobalDefaultsAsync()
{
var app = await _worker.GetAppSettingsAsync();
_globalModel = app?.DefaultModel ?? ModelRegistry.DefaultAlias;
_globalMaxTurns = app?.DefaultMaxTurns ?? 100;
}
private void ApplyConfig(string? model, int? maxTurns, string? systemPrompt, string? agentPath)
{
Model = string.IsNullOrWhiteSpace(model) ? null : model!;
MaxTurns = maxTurns is int mt ? mt : (decimal?)null;
SystemPrompt = systemPrompt ?? "";
SelectedAgent = string.IsNullOrWhiteSpace(agentPath)
? Agents[0]
: (Agents.FirstOrDefault(a => a.Path == agentPath) ?? Agents[0]);
}
[RelayCommand] private void ResetModel() => Model = null;
[RelayCommand] private void ResetTurns() => MaxTurns = null;
[RelayCommand] private void ResetAgent() => SelectedAgent = Agents.Count > 0 ? Agents[0] : null;
[RelayCommand]
private void ResetAll()
{
Model = null;
MaxTurns = null;
SystemPrompt = "";
SelectedAgent = Agents.Count > 0 ? Agents[0] : null;
}
}

View File

@@ -1,196 +0,0 @@
using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using ClaudeDo.Data.Models;
using ClaudeDo.Ui.Helpers;
using ClaudeDo.Ui.Localization;
using ClaudeDo.Ui.Services;
namespace ClaudeDo.Ui.ViewModels.Islands;
public sealed partial class AgentSettingsSectionViewModel : ViewModelBase, IDisposable
{
private readonly IWorkerClient _worker;
private readonly EventHandler _langChangedHandler;
internal string? TaskId { get; set; }
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(IsAgentSectionEnabled))]
private bool _isRunning;
public bool IsAgentSectionEnabled => !IsRunning;
[ObservableProperty] private string? _taskModelSelection;
[ObservableProperty] private string _taskSystemPrompt = "";
[ObservableProperty] private AgentInfo? _taskSelectedAgent;
[ObservableProperty] private decimal? _taskMaxTurns;
[ObservableProperty] private string _modelBadge = "";
[ObservableProperty] private string _modelInheritedHint = "";
[ObservableProperty] private string _turnsBadge = "";
[ObservableProperty] private string _turnsInheritedHint = "";
[ObservableProperty] private string _agentBadge = "";
[ObservableProperty] private string _effectiveSystemPromptHint = "";
private string _globalModel = ModelRegistry.DefaultAlias;
private int _globalMaxTurns = 100;
private string? _listModel;
private int? _listMaxTurns;
private string? _listAgentName;
private bool _suppressAgentSave;
private CancellationTokenSource? _agentSaveCts;
public int EffectiveMaxTurns =>
TaskMaxTurns is decimal t ? (int)t : (_listMaxTurns ?? _globalMaxTurns);
public ObservableCollection<string> TaskModelOptions { get; } = new(ModelRegistry.Aliases);
public ObservableCollection<AgentInfo> TaskAgentOptions { get; } = new();
public AgentSettingsSectionViewModel(IWorkerClient worker)
{
_worker = worker;
_langChangedHandler = (_, _) =>
{
RecomputeModelBadge();
RecomputeTurnsBadge();
RecomputeAgentBadge();
};
Loc.LanguageChanged += _langChangedHandler;
}
public void Dispose() => Loc.LanguageChanged -= _langChangedHandler;
partial void OnTaskModelSelectionChanged(string? value) { RecomputeModelBadge(); QueueAgentSave(); }
partial void OnTaskMaxTurnsChanged(decimal? value)
{
RecomputeTurnsBadge();
OnPropertyChanged(nameof(EffectiveMaxTurns));
QueueAgentSave();
}
partial void OnTaskSystemPromptChanged(string value) => QueueAgentSave();
partial void OnTaskSelectedAgentChanged(AgentInfo? value) { RecomputeAgentBadge(); QueueAgentSave(); }
private void RecomputeModelBadge()
{
var (value, source) = InheritanceResolver.Resolve(TaskModelSelection, _listModel, _globalModel);
ModelInheritedHint = value;
ModelBadge = BadgeFor(source, !string.IsNullOrWhiteSpace(TaskModelSelection));
}
private void RecomputeTurnsBadge()
{
var (value, source) = InheritanceResolver.Resolve(
TaskMaxTurns?.ToString(), _listMaxTurns?.ToString(), _globalMaxTurns.ToString());
TurnsInheritedHint = value;
TurnsBadge = BadgeFor(source, TaskMaxTurns is not null);
}
private void RecomputeAgentBadge()
{
var taskSet = TaskSelectedAgent is not null && !string.IsNullOrWhiteSpace(TaskSelectedAgent.Path);
var (_, source) = InheritanceResolver.Resolve(
taskSet ? TaskSelectedAgent!.Path : null, _listAgentName, null);
AgentBadge = BadgeFor(source, taskSet);
}
private static string BadgeFor(InheritSource source, bool taskSet) => taskSet
? Loc.T("settings.inherit.overrideBadge")
: source == InheritSource.List
? Loc.T("settings.inherit.inheritedFromList")
: Loc.T("settings.inherit.inheritedFromGlobal");
private void QueueAgentSave()
{
if (_suppressAgentSave || TaskId is null) return;
_agentSaveCts?.Cancel();
_agentSaveCts = new CancellationTokenSource();
_ = SaveAgentSettingsAsync(_agentSaveCts.Token);
}
private async System.Threading.Tasks.Task SaveAgentSettingsAsync(CancellationToken ct)
{
try
{
await System.Threading.Tasks.Task.Delay(300, ct);
if (TaskId is null) return;
var model = string.IsNullOrWhiteSpace(TaskModelSelection) ? null : TaskModelSelection;
var sp = string.IsNullOrWhiteSpace(TaskSystemPrompt) ? null : TaskSystemPrompt;
var ap = TaskSelectedAgent is null || string.IsNullOrWhiteSpace(TaskSelectedAgent.Path)
? null : TaskSelectedAgent.Path;
var turns = TaskMaxTurns is decimal d ? (int?)d : null;
await _worker.UpdateTaskAgentSettingsAsync(
new UpdateTaskAgentSettingsDto(TaskId, model, sp, ap, turns));
}
catch (OperationCanceledException) { }
catch { }
}
internal async System.Threading.Tasks.Task LoadAsync(
ClaudeDo.Data.Models.TaskEntity entity, CancellationToken ct)
{
_suppressAgentSave = true;
try
{
TaskAgentOptions.Clear();
TaskAgentOptions.Add(new AgentInfo("(inherited)", "", ""));
var agents = await _worker.GetAgentsAsync();
foreach (var a in agents) TaskAgentOptions.Add(a);
TaskModelSelection = string.IsNullOrWhiteSpace(entity.Model) ? null : entity.Model!;
TaskMaxTurns = entity.MaxTurns is int tmt ? tmt : (decimal?)null;
TaskSystemPrompt = entity.SystemPrompt ?? "";
TaskSelectedAgent = string.IsNullOrWhiteSpace(entity.AgentPath)
? TaskAgentOptions[0]
: (TaskAgentOptions.FirstOrDefault(a => a.Path == entity.AgentPath) ?? TaskAgentOptions[0]);
var listCfg = await _worker.GetListConfigAsync(entity.ListId);
var app = await _worker.GetAppSettingsAsync();
_globalModel = app?.DefaultModel ?? ModelRegistry.DefaultAlias;
_globalMaxTurns = app?.DefaultMaxTurns ?? 100;
_listModel = listCfg?.Model;
_listMaxTurns = listCfg?.MaxTurns;
_listAgentName = string.IsNullOrWhiteSpace(listCfg?.AgentPath)
? null : System.IO.Path.GetFileName(listCfg!.AgentPath!);
EffectiveSystemPromptHint = string.IsNullOrWhiteSpace(listCfg?.SystemPrompt)
? "" : listCfg!.SystemPrompt!;
RecomputeModelBadge();
RecomputeTurnsBadge();
RecomputeAgentBadge();
OnPropertyChanged(nameof(EffectiveMaxTurns));
}
finally
{
_suppressAgentSave = false;
}
}
internal void Clear()
{
_suppressAgentSave = true;
try
{
TaskModelSelection = null;
TaskMaxTurns = null;
TaskSystemPrompt = "";
TaskSelectedAgent = null;
}
finally
{
_suppressAgentSave = false;
}
EffectiveSystemPromptHint = "";
TaskId = null;
}
[RelayCommand] private void ResetTaskModel() => TaskModelSelection = null;
[RelayCommand] private void ResetTaskTurns() => TaskMaxTurns = null;
[RelayCommand] private void ResetTaskAgent() =>
TaskSelectedAgent = TaskAgentOptions.Count > 0 ? TaskAgentOptions[0] : null;
}

View File

@@ -9,6 +9,7 @@ using ClaudeDo.Ui.Helpers;
using ClaudeDo.Ui.Localization;
using ClaudeDo.Ui.Services;
using ClaudeDo.Ui.Services.Interfaces;
using ClaudeDo.Ui.ViewModels.Agent;
using ClaudeDo.Ui.ViewModels.Modals;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
@@ -56,7 +57,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
private readonly IMergeCoordinator _merge;
// ── Section view models ───────────────────────────────────────────────────
public AgentSettingsSectionViewModel AgentSettings { get; }
public AgentConfigEditorViewModel AgentSettings { get; }
public MergeSectionViewModel Merge { get; }
public PrepPanelViewModel Prep { get; }
@@ -425,7 +426,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
_notesApi = notesApi;
_merge = merge;
AgentSettings = new AgentSettingsSectionViewModel(worker);
AgentSettings = new AgentConfigEditorViewModel(worker, AgentConfigScope.Task);
Merge = new MergeSectionViewModel(worker, services);
Prep = new PrepPanelViewModel(worker);
@@ -436,7 +437,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
AgentSettings.PropertyChanged += (_, e) =>
{
if (e.PropertyName == nameof(AgentSettingsSectionViewModel.EffectiveMaxTurns))
if (e.PropertyName == nameof(AgentConfigEditorViewModel.EffectiveMaxTurns))
OnPropertyChanged(nameof(TurnsText));
};
@@ -685,8 +686,7 @@ public sealed partial class DetailsIslandViewModel : ViewModelBase, IDisposable
Merge.SyncWorktree(WorktreePath, WorktreeBaseCommit, WorktreeHeadCommit,
WorktreeStateLabel, _listWorkingDir);
AgentSettings.TaskId = row.Id;
await AgentSettings.LoadAsync(entity, ct);
await AgentSettings.LoadForTaskAsync(entity, ct);
ct.ThrowIfCancellationRequested();
var runRepo = new TaskRunRepository(ctx);

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;
}
}