From 84a518a9c9b85476fb409d168a64c210a9c401f6 Mon Sep 17 00:00:00 2001 From: Nathan Date: Wed, 17 Dec 2025 16:55:36 -0700 Subject: [PATCH] fix sheepit GPU selection --- .../2025-12-17_23-08Z-build-status-query.md | 5242 +++++++++++++++++ ViewModels/WorkerEditViewModel.cs | 4 +- Views/WorkerEditWindow.axaml | 6 +- 3 files changed, 5248 insertions(+), 4 deletions(-) diff --git a/.specstory/history/2025-12-17_23-08Z-build-status-query.md b/.specstory/history/2025-12-17_23-08Z-build-status-query.md index be5fd48..7e851a1 100644 --- a/.specstory/history/2025-12-17_23-08Z-build-status-query.md +++ b/.specstory/history/2025-12-17_23-08Z-build-status-query.md @@ -34201,3 +34201,5245 @@ The fixes resolved the pipeline input binding issue, and the script now handles --- +_**User**_ + +even if attach is functional, the start function may not be. selecting the GPU in worker settings doesn't appear to do anything; if I open settings, it must be selected again. + +--- + +_**Agent (model default, mode Plan)**_ + + +Investigating GPU selection persistence and how it's used when starting workers. Reviewing the relevant code: + + +--- + + +
Tool use: **read_file_v2** • Read file: Models/WorkerTypeConfig.cs + +
+
+ +--- + + +
Tool use: **read_file_v2** • Read file: ViewModels/WorkerEditViewModel.cs + +
+
+ +--- + + +
Tool use: **read_file_v2** • Read file: Views/WorkerEditWindow.axaml + +
+
+ +--- + + +
+Tool use: **ripgrep_raw_search** + + +Parameters: + +```json +{ + "pattern": "Gpu|GPU", + "path": ".", + "caseInsensitive": true +} +``` +Result: + +```json +{ + "success": { + "pattern": "Gpu|GPU", + "path": ".", + "outputMode": "content", + "workspaceResults": { + "c:\\Users\\Nathan\\Desktop\\UFL": { + "content": { + "matches": [ + { + "file": "ViewModels/WorkerEditViewModel.cs", + "matches": [ + { + "lineNumber": 18, + "content": " private string _sheepItGpu = \"OPTIX_0\";" + }, + { + "lineNumber": 87, + "content": " public string SheepItGpu" + }, + { + "lineNumber": 89, + "content": " get => _sheepItGpu;" + }, + { + "lineNumber": 90, + "content": " set => SetAndRaise(ref _sheepItGpu, value);" + }, + { + "lineNumber": 108, + "content": " SheepItGpu = worker.WorkerTypes.SheepIt.Gpu;" + }, + { + "lineNumber": 147, + "content": " Gpu = SheepItGpu" + } + ] + }, + { + "file": "Models\\WorkerTypeConfig.cs", + "matches": [ + { + "lineNumber": 9, + "content": " [JsonPropertyName(\"gpu\")]" + }, + { + "lineNumber": 10, + "content": " public string Gpu { get; set; } = string.Empty;" + } + ] + }, + { + "file": ".gitignore", + "matches": [ + { + "lineNumber": 6, + "content": "[Dd]ebugPublic/" + }, + { + "lineNumber": 37, + "content": "[Dd]ebugPublic/" + }, + { + "lineNumber": 80, + "content": "[Dd]ebugPublic/" + }, + { + "lineNumber": 384, + "content": "# NVidia Nsight GPU debugger configuration file" + } + ] + }, + { + "file": "README.md", + "matches": [ + { + "lineNumber": 62, + "content": " \"gpu\": \"CPU\"" + } + ] + }, + { + "file": "ViewModels\\WorkerEditViewModel.cs", + "matches": [ + { + "lineNumber": 18, + "content": " private string _sheepItGpu = \"OPTIX_0\";" + }, + { + "lineNumber": 87, + "content": " public string SheepItGpu" + }, + { + "lineNumber": 89, + "content": " get => _sheepItGpu;" + }, + { + "lineNumber": 90, + "content": " set => SetAndRaise(ref _sheepItGpu, value);" + }, + { + "lineNumber": 108, + "content": " SheepItGpu = worker.WorkerTypes.SheepIt.Gpu;" + }, + { + "lineNumber": 147, + "content": " Gpu = SheepItGpu" + } + ] + }, + { + "file": ".specstory/history/2025-12-17_22-32Z-readme-for-sheepit-worker-incompatibility-fix.md", + "matches": [ + { + "lineNumber": 228, + "content": "+ \"gpu\": \"CPU\"" + }, + { + "lineNumber": 406, + "content": "| `history\\2025-05-06_20-07Z-switching-to-optix-gpu-rendering.md` |" + }, + { + "lineNumber": 596, + "content": "+ - Switched to OptiX GPU rendering" + } + ] + }, + { + "file": "Services\\WorkerControllerService.cs", + "matches": [ + { + "lineNumber": 145, + "content": " '-gpu', '{sheepIt.Gpu}', '-login', '{safeUser}', '-password', '{safeKey}')" + } + ] + }, + { + "file": "Views\\WorkerEditWindow.axaml", + "matches": [ + { + "lineNumber": 36, + "content": " <TextBlock Text=\"GPU:\" IsVisible=\"{Binding HasSheepIt}\"/>" + }, + { + "lineNumber": 37, + "content": " <ComboBox Name=\"GpuComboBox\" IsVisible=\"{Binding HasSheepIt}\" SelectedItem=\"{Binding SheepItGpu}\">" + } + ] + }, + { + "file": "CHANGELOG.md", + "matches": [ + { + "lineNumber": 98, + "content": "- Switched to OptiX GPU rendering" + } + ] + }, + { + "file": "Views/WorkerEditWindow.axaml", + "matches": [ + { + "lineNumber": 36, + "content": " <TextBlock Text=\"GPU:\" IsVisible=\"{Binding HasSheepIt}\"/>" + }, + { + "lineNumber": 37, + "content": " <ComboBox Name=\"GpuComboBox\" IsVisible=\"{Binding HasSheepIt}\" SelectedItem=\"{Binding SheepItGpu}\">" + } + ] + }, + { + "file": "Models/WorkerTypeConfig.cs", + "matches": [ + { + "lineNumber": 9, + "content": " [JsonPropertyName(\"gpu\")]" + }, + { + "lineNumber": 10, + "content": " public string Gpu { get; set; } = string.Empty;" + } + ] + }, + { + "file": "Services/WorkerControllerService.cs", + "matches": [ + { + "lineNumber": 145, + "content": " '-gpu', '{sheepIt.Gpu}', '-login', '{safeUser}', '-password', '{safeKey}')" + } + ] + } + ], + "totalLines": 31, + "totalMatchedLines": 31 + } + } + } + } +} +``` +Status: **completed** + + +
+
+ +--- + + +
Tool use: **read_file_v2** • Read file: Services/WorkerControllerService.cs + +
+
+ +--- + + +Checking how the ComboBox binding works and how the configuration is saved: + + +--- + + +
Tool use: **read_file_v2** • Read file: Services/ConfigService.cs + +
+
+ +--- + + +
Tool use: **read_file_v2** • Read file: Views/WorkerEditWindow.axaml.cs + +
+
+ +--- + + +
+Tool use: **semantic_search_full** + + +Parameters: + +```json +{ + "query": "How is the GPU ComboBox selection saved and loaded in the worker edit window?", + "includePattern": "Views", + "topK": 10, + "explanation": "" +} +``` +Result: + +```json +{ + "codeResults": [ + { + "codeBlock": { + "relativeWorkspacePath": ".\\Views\\WorkerEditWindow.axaml", + "range": { + "startPosition": { + "line": 27 + }, + "endPosition": { + "line": 53 + } + }, + "contents": " </StackPanel>\n </TabItem>\n\n <!-- SheepIt Tab -->\n <TabItem Header=\"SheepIt\">\n <StackPanel Margin=\"10\" Spacing=\"10\">\n <CheckBox Name=\"HasSheepItCheckBox\" Content=\"Enable SheepIt Worker\" IsChecked=\"{Binding HasSheepIt}\" Margin=\"0,0,0,10\"/>\n \n <TextBlock Text=\"GPU:\" IsVisible=\"{Binding HasSheepIt}\"/>\n <ComboBox Name=\"GpuComboBox\" IsVisible=\"{Binding HasSheepIt}\" SelectedItem=\"{Binding SheepItGpu}\">\n <ComboBox.Items>\n <ComboBoxItem Content=\"OPTIX_0\"/>\n <ComboBoxItem Content=\"CUDA_0\"/>\n <ComboBoxItem Content=\"OPENCL_0\"/>\n </ComboBox.Items>\n </ComboBox>\n \n <TextBlock Text=\"Note: Username and Render Key are configured in Global Settings.\" \n IsVisible=\"{Binding HasSheepIt}\" \n Margin=\"0,10,0,0\"\n Foreground=\"Gray\"\n TextWrapping=\"Wrap\"/>\n </StackPanel>\n </TabItem>\n\n <!-- Flamenco Tab -->", + "signatures": {}, + "detailedLines": [ + { + "text": " </StackPanel>", + "lineNumber": 28 + }, + { + "text": " </TabItem>", + "lineNumber": 29 + }, + { + "lineNumber": 30 + }, + { + "text": " <!-- SheepIt Tab -->", + "lineNumber": 31 + }, + { + "text": " <TabItem Header=\"SheepIt\">", + "lineNumber": 32 + }, + { + "text": " <StackPanel Margin=\"10\" Spacing=\"10\">", + "lineNumber": 33 + }, + { + "text": " <CheckBox Name=\"HasSheepItCheckBox\" Content=\"Enable SheepIt Worker\" IsChecked=\"{Binding HasSheepIt}\" Margin=\"0,0,0,10\"/>", + "lineNumber": 34 + }, + { + "text": " ", + "lineNumber": 35 + }, + { + "text": " <TextBlock Text=\"GPU:\" IsVisible=\"{Binding HasSheepIt}\"/>", + "lineNumber": 36 + }, + { + "text": " <ComboBox Name=\"GpuComboBox\" IsVisible=\"{Binding HasSheepIt}\" SelectedItem=\"{Binding SheepItGpu}\">", + "lineNumber": 37 + }, + { + "text": " <ComboBox.Items>", + "lineNumber": 38 + }, + { + "text": " <ComboBoxItem Content=\"OPTIX_0\"/>", + "lineNumber": 39 + }, + { + "text": " <ComboBoxItem Content=\"CUDA_0\"/>", + "lineNumber": 40 + }, + { + "text": " <ComboBoxItem Content=\"OPENCL_0\"/>", + "lineNumber": 41 + }, + { + "text": " </ComboBox.Items>", + "lineNumber": 42 + }, + { + "text": " </ComboBox>", + "lineNumber": 43 + }, + { + "text": " ", + "lineNumber": 44 + }, + { + "text": " <TextBlock Text=\"Note: Username and Render Key are configured in Global Settings.\" ", + "lineNumber": 45 + }, + { + "text": " IsVisible=\"{Binding HasSheepIt}\" ", + "lineNumber": 46 + }, + { + "text": " Margin=\"0,10,0,0\"", + "lineNumber": 47 + }, + { + "text": " Foreground=\"Gray\"", + "lineNumber": 48 + }, + { + "text": " TextWrapping=\"Wrap\"/>", + "lineNumber": 49 + }, + { + "text": " </StackPanel>", + "lineNumber": 50 + }, + { + "text": " </TabItem>", + "lineNumber": 51 + }, + { + "lineNumber": 52 + }, + { + "text": " <!-- Flamenco Tab -->", + "lineNumber": 53 + } + ] + }, + "score": 0.47021031379699707 + }, + { + "codeBlock": { + "relativeWorkspacePath": ".\\ViewModels\\WorkerEditViewModel.cs", + "range": { + "startPosition": { + "line": 65 + }, + "endPosition": { + "line": 127 + } + }, + "contents": " set => SetAndRaise(ref _sshPort, value);\n }\n\n public string SshArgs\n {\n get => _sshArgs;\n set => SetAndRaise(ref _sshArgs, value);\n }\n\n public bool HasSheepIt\n {\n get => _hasSheepIt;\n set => SetAndRaise(ref _hasSheepIt, value);\n }\n\n public bool HasFlamenco\n {\n get => _hasFlamenco;\n set => SetAndRaise(ref _hasFlamenco, value);\n }\n\n public string SheepItGpu\n {\n get => _sheepItGpu;\n set => SetAndRaise(ref _sheepItGpu, value);\n }\n\n public ObservableCollection<string> NetworkDrives { get; }\n public ObservableCollection<string> NetworkPaths { get; }\n\n private void LoadWorker(WorkerConfig worker)\n {\n Id = worker.Id;\n Name = worker.Name;\n Enabled = worker.Enabled;\n SshHost = worker.Ssh.Host;\n SshPort = worker.Ssh.Port;\n SshArgs = worker.Ssh.Args;\n\n if (worker.WorkerTypes.SheepIt != null)\n {\n HasSheepIt = true;\n SheepItGpu = worker.WorkerTypes.SheepIt.Gpu;\n }\n\n if (worker.WorkerTypes.Flamenco != null)\n {\n HasFlamenco = true;\n NetworkDrives.Clear();\n foreach (var drive in worker.WorkerTypes.Flamenco.NetworkDrives)\n {\n NetworkDrives.Add(drive);\n }\n NetworkPaths.Clear();\n foreach (var path in worker.WorkerTypes.Flamenco.NetworkPaths)\n {\n NetworkPaths.Add(path);\n }\n }\n }\n\n public WorkerConfig ToWorkerConfig()", + "signatures": {}, + "detailedLines": [ + { + "text": " set => SetAndRaise(ref _sshPort, value);", + "lineNumber": 66 + }, + { + "text": " }", + "lineNumber": 67 + }, + { + "lineNumber": 68 + }, + { + "text": " public string SshArgs", + "lineNumber": 69 + }, + { + "text": " {", + "lineNumber": 70 + }, + { + "text": " get => _sshArgs;", + "lineNumber": 71 + }, + { + "text": " set => SetAndRaise(ref _sshArgs, value);", + "lineNumber": 72 + }, + { + "text": " }", + "lineNumber": 73 + }, + { + "lineNumber": 74 + }, + { + "text": " public bool HasSheepIt", + "lineNumber": 75 + }, + { + "text": " {", + "lineNumber": 76 + }, + { + "text": " get => _hasSheepIt;", + "lineNumber": 77 + }, + { + "text": " set => SetAndRaise(ref _hasSheepIt, value);", + "lineNumber": 78 + }, + { + "text": " }", + "lineNumber": 79 + }, + { + "lineNumber": 80 + }, + { + "text": " public bool HasFlamenco", + "lineNumber": 81 + }, + { + "text": " {", + "lineNumber": 82 + }, + { + "text": " get => _hasFlamenco;", + "lineNumber": 83 + }, + { + "text": " set => SetAndRaise(ref _hasFlamenco, value);", + "lineNumber": 84 + }, + { + "text": " }", + "lineNumber": 85 + }, + { + "lineNumber": 86 + }, + { + "text": " public string SheepItGpu", + "lineNumber": 87 + }, + { + "text": " {", + "lineNumber": 88 + }, + { + "text": " get => _sheepItGpu;", + "lineNumber": 89 + }, + { + "text": " set => SetAndRaise(ref _sheepItGpu, value);", + "lineNumber": 90 + }, + { + "text": " }", + "lineNumber": 91 + }, + { + "lineNumber": 92 + }, + { + "text": " public ObservableCollection<string> NetworkDrives { get; }", + "lineNumber": 93 + }, + { + "text": " public ObservableCollection<string> NetworkPaths { get; }", + "lineNumber": 94 + }, + { + "lineNumber": 95 + }, + { + "text": " private void LoadWorker(WorkerConfig worker)", + "lineNumber": 96 + }, + { + "text": " {", + "lineNumber": 97 + }, + { + "text": " Id = worker.Id;", + "lineNumber": 98 + }, + { + "text": " Name = worker.Name;", + "lineNumber": 99 + }, + { + "text": " Enabled = worker.Enabled;", + "lineNumber": 100 + }, + { + "text": " SshHost = worker.Ssh.Host;", + "lineNumber": 101 + }, + { + "text": " SshPort = worker.Ssh.Port;", + "lineNumber": 102 + }, + { + "text": " SshArgs = worker.Ssh.Args;", + "lineNumber": 103 + }, + { + "lineNumber": 104 + }, + { + "text": " if (worker.WorkerTypes.SheepIt != null)", + "lineNumber": 105 + }, + { + "text": " {", + "lineNumber": 106 + }, + { + "text": " HasSheepIt = true;", + "lineNumber": 107 + }, + { + "text": " SheepItGpu = worker.WorkerTypes.SheepIt.Gpu;", + "lineNumber": 108 + }, + { + "text": " }", + "lineNumber": 109 + }, + { + "lineNumber": 110 + }, + { + "text": " if (worker.WorkerTypes.Flamenco != null)", + "lineNumber": 111 + }, + { + "text": " {", + "lineNumber": 112 + }, + { + "text": " HasFlamenco = true;", + "lineNumber": 113 + }, + { + "text": " NetworkDrives.Clear();", + "lineNumber": 114 + }, + { + "text": " foreach (var drive in worker.WorkerTypes.Flamenco.NetworkDrives)", + "lineNumber": 115 + }, + { + "text": " {", + "lineNumber": 116 + }, + { + "text": " NetworkDrives.Add(drive);", + "lineNumber": 117 + }, + { + "text": " }", + "lineNumber": 118 + }, + { + "text": " NetworkPaths.Clear();", + "lineNumber": 119 + }, + { + "text": " foreach (var path in worker.WorkerTypes.Flamenco.NetworkPaths)", + "lineNumber": 120 + }, + { + "text": " {", + "lineNumber": 121 + }, + { + "text": " NetworkPaths.Add(path);", + "lineNumber": 122 + }, + { + "text": " }", + "lineNumber": 123 + }, + { + "text": " }", + "lineNumber": 124 + }, + { + "text": " }", + "lineNumber": 125 + }, + { + "lineNumber": 126 + }, + { + "text": " public WorkerConfig ToWorkerConfig()", + "lineNumber": 127 + } + ] + }, + "score": 0.428444504737854 + }, + { + "codeBlock": { + "relativeWorkspacePath": ".\\ViewModels\\WorkerEditViewModel.cs", + "range": { + "startPosition": {}, + "endPosition": { + "line": 71 + } + }, + "contents": "using System.Collections.ObjectModel;\nusing System.Linq;\nusing UnifiedFarmLauncher.Models;\nusing UnifiedFarmLauncher.Services;\n\nnamespace UnifiedFarmLauncher.ViewModels\n{\n public class WorkerEditViewModel : ViewModelBase\n {\n private readonly ConfigService _configService;\n private readonly bool _isNew;\n private int _id;\n private string _name = string.Empty;\n private bool _enabled = true;\n private string _sshHost = string.Empty;\n private int _sshPort = 22;\n private string _sshArgs = string.Empty;\n private string _sheepItGpu = \"OPTIX_0\";\n private bool _hasSheepIt;\n private bool _hasFlamenco;\n\n public WorkerEditViewModel(ConfigService configService, WorkerConfig? worker = null)\n {\n _configService = configService;\n _isNew = worker == null;\n NetworkDrives = new ObservableCollection<string>();\n NetworkPaths = new ObservableCollection<string>();\n\n if (worker != null)\n {\n LoadWorker(worker);\n }\n else\n {\n _id = _configService.GetNextWorkerId();\n }\n }\n\n public int Id\n {\n get => _id;\n set => SetAndRaise(ref _id, value);\n }\n\n public string Name\n {\n get => _name;\n set => SetAndRaise(ref _name, value);\n }\n\n public bool Enabled\n {\n get => _enabled;\n set => SetAndRaise(ref _enabled, value);\n }\n\n public string SshHost\n {\n get => _sshHost;\n set => SetAndRaise(ref _sshHost, value);\n }\n\n public int SshPort\n {\n get => _sshPort;\n set => SetAndRaise(ref _sshPort, value);\n }\n\n public string SshArgs\n {\n get => _sshArgs;", + "signatures": {}, + "detailedLines": [ + { + "text": "using System.Collections.ObjectModel;", + "lineNumber": 1 + }, + { + "text": "using System.Linq;", + "lineNumber": 2 + }, + { + "text": "using UnifiedFarmLauncher.Models;", + "lineNumber": 3 + }, + { + "text": "using UnifiedFarmLauncher.Services;", + "lineNumber": 4 + }, + { + "lineNumber": 5 + }, + { + "text": "namespace UnifiedFarmLauncher.ViewModels", + "lineNumber": 6 + }, + { + "text": "{", + "lineNumber": 7 + }, + { + "text": " public class WorkerEditViewModel : ViewModelBase", + "lineNumber": 8 + }, + { + "text": " {", + "lineNumber": 9 + }, + { + "text": " private readonly ConfigService _configService;", + "lineNumber": 10 + }, + { + "text": " private readonly bool _isNew;", + "lineNumber": 11 + }, + { + "text": " private int _id;", + "lineNumber": 12 + }, + { + "text": " private string _name = string.Empty;", + "lineNumber": 13 + }, + { + "text": " private bool _enabled = true;", + "lineNumber": 14 + }, + { + "text": " private string _sshHost = string.Empty;", + "lineNumber": 15 + }, + { + "text": " private int _sshPort = 22;", + "lineNumber": 16 + }, + { + "text": " private string _sshArgs = string.Empty;", + "lineNumber": 17 + }, + { + "text": " private string _sheepItGpu = \"OPTIX_0\";", + "lineNumber": 18 + }, + { + "text": " private bool _hasSheepIt;", + "lineNumber": 19 + }, + { + "text": " private bool _hasFlamenco;", + "lineNumber": 20 + }, + { + "lineNumber": 21 + }, + { + "text": " public WorkerEditViewModel(ConfigService configService, WorkerConfig? worker = null)", + "lineNumber": 22 + }, + { + "text": " {", + "lineNumber": 23 + }, + { + "text": " _configService = configService;", + "lineNumber": 24 + }, + { + "text": " _isNew = worker == null;", + "lineNumber": 25 + }, + { + "text": " NetworkDrives = new ObservableCollection<string>();", + "lineNumber": 26 + }, + { + "text": " NetworkPaths = new ObservableCollection<string>();", + "lineNumber": 27 + }, + { + "lineNumber": 28 + }, + { + "text": " if (worker != null)", + "lineNumber": 29 + }, + { + "text": " {", + "lineNumber": 30 + }, + { + "text": " LoadWorker(worker);", + "lineNumber": 31 + }, + { + "text": " }", + "lineNumber": 32 + }, + { + "text": " else", + "lineNumber": 33 + }, + { + "text": " {", + "lineNumber": 34 + }, + { + "text": " _id = _configService.GetNextWorkerId();", + "lineNumber": 35 + }, + { + "text": " }", + "lineNumber": 36 + }, + { + "text": " }", + "lineNumber": 37 + }, + { + "lineNumber": 38 + }, + { + "text": " public int Id", + "lineNumber": 39 + }, + { + "text": " {", + "lineNumber": 40 + }, + { + "text": " get => _id;", + "lineNumber": 41 + }, + { + "text": " set => SetAndRaise(ref _id, value);", + "lineNumber": 42 + }, + { + "text": " }", + "lineNumber": 43 + }, + { + "lineNumber": 44 + }, + { + "text": " public string Name", + "lineNumber": 45 + }, + { + "text": " {", + "lineNumber": 46 + }, + { + "text": " get => _name;", + "lineNumber": 47 + }, + { + "text": " set => SetAndRaise(ref _name, value);", + "lineNumber": 48 + }, + { + "text": " }", + "lineNumber": 49 + }, + { + "lineNumber": 50 + }, + { + "text": " public bool Enabled", + "lineNumber": 51 + }, + { + "text": " {", + "lineNumber": 52 + }, + { + "text": " get => _enabled;", + "lineNumber": 53 + }, + { + "text": " set => SetAndRaise(ref _enabled, value);", + "lineNumber": 54 + }, + { + "text": " }", + "lineNumber": 55 + }, + { + "lineNumber": 56 + }, + { + "text": " public string SshHost", + "lineNumber": 57 + }, + { + "text": " {", + "lineNumber": 58 + }, + { + "text": " get => _sshHost;", + "lineNumber": 59 + }, + { + "text": " set => SetAndRaise(ref _sshHost, value);", + "lineNumber": 60 + }, + { + "text": " }", + "lineNumber": 61 + }, + { + "lineNumber": 62 + }, + { + "text": " public int SshPort", + "lineNumber": 63 + }, + { + "text": " {", + "lineNumber": 64 + }, + { + "text": " get => _sshPort;", + "lineNumber": 65 + }, + { + "text": " set => SetAndRaise(ref _sshPort, value);", + "lineNumber": 66 + }, + { + "text": " }", + "lineNumber": 67 + }, + { + "lineNumber": 68 + }, + { + "text": " public string SshArgs", + "lineNumber": 69 + }, + { + "text": " {", + "lineNumber": 70 + }, + { + "text": " get => _sshArgs;", + "lineNumber": 71 + } + ] + }, + "score": 0.42505720257759094 + }, + { + "codeBlock": { + "relativeWorkspacePath": ".\\ViewModels\\WorkerEditViewModel.cs", + "range": { + "startPosition": { + "line": 122, + "column": 16 + }, + "endPosition": { + "line": 177 + } + }, + "contents": "}\n }\n }\n\n public WorkerConfig ToWorkerConfig()\n {\n var worker = new WorkerConfig\n {\n Id = Id,\n Name = Name,\n Enabled = Enabled,\n Ssh = new SshConfig\n {\n Host = SshHost,\n Port = SshPort,\n Args = SshArgs\n },\n WorkerTypes = new WorkerTypeConfig()\n };\n\n if (HasSheepIt)\n {\n worker.WorkerTypes.SheepIt = new SheepItConfig\n {\n Gpu = SheepItGpu\n };\n }\n\n if (HasFlamenco)\n {\n worker.WorkerTypes.Flamenco = new FlamencoConfig\n {\n NetworkDrives = NetworkDrives.ToList(),\n NetworkPaths = NetworkPaths.ToList()\n };\n }\n\n return worker;\n }\n\n public void Save()\n {\n var worker = ToWorkerConfig();\n if (_isNew)\n {\n _configService.AddWorker(worker);\n }\n else\n {\n _configService.UpdateWorker(worker);\n }\n }\n }\n}", + "signatures": {}, + "detailedLines": [ + { + "text": "}", + "lineNumber": 123 + }, + { + "text": " }", + "lineNumber": 124 + }, + { + "text": " }", + "lineNumber": 125 + }, + { + "lineNumber": 126 + }, + { + "text": " public WorkerConfig ToWorkerConfig()", + "lineNumber": 127 + }, + { + "text": " {", + "lineNumber": 128 + }, + { + "text": " var worker = new WorkerConfig", + "lineNumber": 129 + }, + { + "text": " {", + "lineNumber": 130 + }, + { + "text": " Id = Id,", + "lineNumber": 131 + }, + { + "text": " Name = Name,", + "lineNumber": 132 + }, + { + "text": " Enabled = Enabled,", + "lineNumber": 133 + }, + { + "text": " Ssh = new SshConfig", + "lineNumber": 134 + }, + { + "text": " {", + "lineNumber": 135 + }, + { + "text": " Host = SshHost,", + "lineNumber": 136 + }, + { + "text": " Port = SshPort,", + "lineNumber": 137 + }, + { + "text": " Args = SshArgs", + "lineNumber": 138 + }, + { + "text": " },", + "lineNumber": 139 + }, + { + "text": " WorkerTypes = new WorkerTypeConfig()", + "lineNumber": 140 + }, + { + "text": " };", + "lineNumber": 141 + }, + { + "lineNumber": 142 + }, + { + "text": " if (HasSheepIt)", + "lineNumber": 143 + }, + { + "text": " {", + "lineNumber": 144 + }, + { + "text": " worker.WorkerTypes.SheepIt = new SheepItConfig", + "lineNumber": 145 + }, + { + "text": " {", + "lineNumber": 146 + }, + { + "text": " Gpu = SheepItGpu", + "lineNumber": 147 + }, + { + "text": " };", + "lineNumber": 148 + }, + { + "text": " }", + "lineNumber": 149 + }, + { + "lineNumber": 150 + }, + { + "text": " if (HasFlamenco)", + "lineNumber": 151 + }, + { + "text": " {", + "lineNumber": 152 + }, + { + "text": " worker.WorkerTypes.Flamenco = new FlamencoConfig", + "lineNumber": 153 + }, + { + "text": " {", + "lineNumber": 154 + }, + { + "text": " NetworkDrives = NetworkDrives.ToList(),", + "lineNumber": 155 + }, + { + "text": " NetworkPaths = NetworkPaths.ToList()", + "lineNumber": 156 + }, + { + "text": " };", + "lineNumber": 157 + }, + { + "text": " }", + "lineNumber": 158 + }, + { + "lineNumber": 159 + }, + { + "text": " return worker;", + "lineNumber": 160 + }, + { + "text": " }", + "lineNumber": 161 + }, + { + "lineNumber": 162 + }, + { + "text": " public void Save()", + "lineNumber": 163 + }, + { + "text": " {", + "lineNumber": 164 + }, + { + "text": " var worker = ToWorkerConfig();", + "lineNumber": 165 + }, + { + "text": " if (_isNew)", + "lineNumber": 166 + }, + { + "text": " {", + "lineNumber": 167 + }, + { + "text": " _configService.AddWorker(worker);", + "lineNumber": 168 + }, + { + "text": " }", + "lineNumber": 169 + }, + { + "text": " else", + "lineNumber": 170 + }, + { + "text": " {", + "lineNumber": 171 + }, + { + "text": " _configService.UpdateWorker(worker);", + "lineNumber": 172 + }, + { + "text": " }", + "lineNumber": 173 + }, + { + "text": " }", + "lineNumber": 174 + }, + { + "text": " }", + "lineNumber": 175 + }, + { + "text": "}", + "lineNumber": 176 + } + ] + }, + "score": 0.40253424644470215 + }, + { + "codeBlock": { + "relativeWorkspacePath": ".\\Views\\WorkerEditWindow.axaml", + "range": { + "startPosition": {}, + "endPosition": { + "line": 32, + "column": 16 + } + }, + "contents": "<Window xmlns=\"https://github.com/avaloniaui\"\n xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n xmlns:vm=\"using:UnifiedFarmLauncher.ViewModels\"\n x:Class=\"UnifiedFarmLauncher.Views.WorkerEditWindow\"\n x:DataType=\"vm:WorkerEditViewModel\"\n Title=\"Edit Worker\"\n Width=\"600\" Height=\"700\"\n MinWidth=\"500\" MinHeight=\"600\">\n <Grid RowDefinitions=\"Auto,*,Auto\" Margin=\"10\">\n <!-- Tabs -->\n <TabControl Grid.Row=\"1\" Margin=\"0,10\">\n <!-- Basic Info Tab -->\n <TabItem Header=\"Basic Info\">\n <StackPanel Margin=\"10\" Spacing=\"10\">\n <TextBlock Text=\"Worker Name:\"/>\n <TextBox Name=\"NameTextBox\" Text=\"{Binding Name}\"/>\n \n <CheckBox Name=\"EnabledCheckBox\" Content=\"Enabled\" IsChecked=\"{Binding Enabled}\" Margin=\"0,10,0,0\"/>\n \n <TextBlock Text=\"SSH Host:\" Margin=\"0,10,0,0\"/>\n <TextBox Name=\"SshHostTextBox\" Text=\"{Binding SshHost}\"/>\n \n <TextBlock Text=\"SSH Port:\" Margin=\"0,10,0,0\"/>\n <NumericUpDown Name=\"SshPortNumeric\" Value=\"{Binding SshPort}\" Minimum=\"1\" Maximum=\"65535\"/>\n \n <TextBlock Text=\"SSH Args:\" Margin=\"0,10,0,0\"/>\n <TextBox Name=\"SshArgsTextBox\" Text=\"{Binding SshArgs}\"/>\n </StackPanel>\n </TabItem>\n\n <!-- SheepIt Tab -->\n <TabItem Header=\"SheepIt\">\n ", + "signatures": {}, + "detailedLines": [ + { + "text": "<Window xmlns=\"https://github.com/avaloniaui\"", + "lineNumber": 1 + }, + { + "text": " xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"", + "lineNumber": 2 + }, + { + "text": " xmlns:vm=\"using:UnifiedFarmLauncher.ViewModels\"", + "lineNumber": 3 + }, + { + "text": " x:Class=\"UnifiedFarmLauncher.Views.WorkerEditWindow\"", + "lineNumber": 4 + }, + { + "text": " x:DataType=\"vm:WorkerEditViewModel\"", + "lineNumber": 5 + }, + { + "text": " Title=\"Edit Worker\"", + "lineNumber": 6 + }, + { + "text": " Width=\"600\" Height=\"700\"", + "lineNumber": 7 + }, + { + "text": " MinWidth=\"500\" MinHeight=\"600\">", + "lineNumber": 8 + }, + { + "text": " <Grid RowDefinitions=\"Auto,*,Auto\" Margin=\"10\">", + "lineNumber": 9 + }, + { + "text": " <!-- Tabs -->", + "lineNumber": 10 + }, + { + "text": " <TabControl Grid.Row=\"1\" Margin=\"0,10\">", + "lineNumber": 11 + }, + { + "text": " <!-- Basic Info Tab -->", + "lineNumber": 12 + }, + { + "text": " <TabItem Header=\"Basic Info\">", + "lineNumber": 13 + }, + { + "text": " <StackPanel Margin=\"10\" Spacing=\"10\">", + "lineNumber": 14 + }, + { + "text": " <TextBlock Text=\"Worker Name:\"/>", + "lineNumber": 15 + }, + { + "text": " <TextBox Name=\"NameTextBox\" Text=\"{Binding Name}\"/>", + "lineNumber": 16 + }, + { + "text": " ", + "lineNumber": 17 + }, + { + "text": " <CheckBox Name=\"EnabledCheckBox\" Content=\"Enabled\" IsChecked=\"{Binding Enabled}\" Margin=\"0,10,0,0\"/>", + "lineNumber": 18 + }, + { + "text": " ", + "lineNumber": 19 + }, + { + "text": " <TextBlock Text=\"SSH Host:\" Margin=\"0,10,0,0\"/>", + "lineNumber": 20 + }, + { + "text": " <TextBox Name=\"SshHostTextBox\" Text=\"{Binding SshHost}\"/>", + "lineNumber": 21 + }, + { + "text": " ", + "lineNumber": 22 + }, + { + "text": " <TextBlock Text=\"SSH Port:\" Margin=\"0,10,0,0\"/>", + "lineNumber": 23 + }, + { + "text": " <NumericUpDown Name=\"SshPortNumeric\" Value=\"{Binding SshPort}\" Minimum=\"1\" Maximum=\"65535\"/>", + "lineNumber": 24 + }, + { + "text": " ", + "lineNumber": 25 + }, + { + "text": " <TextBlock Text=\"SSH Args:\" Margin=\"0,10,0,0\"/>", + "lineNumber": 26 + }, + { + "text": " <TextBox Name=\"SshArgsTextBox\" Text=\"{Binding SshArgs}\"/>", + "lineNumber": 27 + }, + { + "text": " </StackPanel>", + "lineNumber": 28 + }, + { + "text": " </TabItem>", + "lineNumber": 29 + }, + { + "lineNumber": 30 + }, + { + "text": " <!-- SheepIt Tab -->", + "lineNumber": 31 + }, + { + "text": " <TabItem Header=\"SheepIt\">", + "lineNumber": 32 + }, + { + "text": " ", + "lineNumber": 33 + } + ] + }, + "score": 0.349617600440979 + }, + { + "codeBlock": { + "relativeWorkspacePath": ".\\Views\\WorkerEditWindow.axaml.cs", + "range": { + "startPosition": {}, + "endPosition": { + "line": 50 + } + }, + "contents": "using System;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing Avalonia.Controls;\nusing Avalonia.Interactivity;\nusing Avalonia.Platform.Storage;\nusing UnifiedFarmLauncher.Models;\nusing UnifiedFarmLauncher.Services;\nusing UnifiedFarmLauncher.ViewModels;\nusing MsBox.Avalonia;\nusing MsBox.Avalonia.Enums;\n\nnamespace UnifiedFarmLauncher.Views\n{\n public partial class WorkerEditWindow : Window\n {\n private readonly WorkerEditViewModel _viewModel;\n private bool _result;\n\n public WorkerEditWindow() : this(null)\n {\n }\n\n public WorkerEditWindow(WorkerConfig? worker)\n {\n InitializeComponent();\n var configService = new ConfigService();\n _viewModel = new WorkerEditViewModel(configService, worker);\n DataContext = _viewModel;\n SetupEventHandlers();\n }\n\n private void InitializeComponent()\n {\n Avalonia.Markup.Xaml.AvaloniaXamlLoader.Load(this);\n }\n\n private void SetupEventHandlers()\n {\n this.FindControl<Button>(\"OkButton\")!.Click += OkButton_Click;\n this.FindControl<Button>(\"CancelButton\")!.Click += CancelButton_Click;\n this.FindControl<Button>(\"AddDriveButton\")!.Click += AddDriveButton_Click;\n this.FindControl<Button>(\"RemoveDriveButton\")!.Click += RemoveDriveButton_Click;\n this.FindControl<Button>(\"AddPathButton\")!.Click += AddPathButton_Click;\n this.FindControl<Button>(\"RemovePathButton\")!.Click += RemovePathButton_Click;\n }\n\n private async void OkButton_Click(object? sender, RoutedEventArgs e)\n {\n if (string.IsNullOrWhiteSpace(_viewModel.Name))", + "signatures": {}, + "detailedLines": [ + { + "text": "using System;", + "lineNumber": 1 + }, + { + "text": "using System.Linq;", + "lineNumber": 2 + }, + { + "text": "using System.Threading.Tasks;", + "lineNumber": 3 + }, + { + "text": "using Avalonia.Controls;", + "lineNumber": 4 + }, + { + "text": "using Avalonia.Interactivity;", + "lineNumber": 5 + }, + { + "text": "using Avalonia.Platform.Storage;", + "lineNumber": 6 + }, + { + "text": "using UnifiedFarmLauncher.Models;", + "lineNumber": 7 + }, + { + "text": "using UnifiedFarmLauncher.Services;", + "lineNumber": 8 + }, + { + "text": "using UnifiedFarmLauncher.ViewModels;", + "lineNumber": 9 + }, + { + "text": "using MsBox.Avalonia;", + "lineNumber": 10 + }, + { + "text": "using MsBox.Avalonia.Enums;", + "lineNumber": 11 + }, + { + "lineNumber": 12 + }, + { + "text": "namespace UnifiedFarmLauncher.Views", + "lineNumber": 13 + }, + { + "text": "{", + "lineNumber": 14 + }, + { + "text": " public partial class WorkerEditWindow : Window", + "lineNumber": 15 + }, + { + "text": " {", + "lineNumber": 16 + }, + { + "text": " private readonly WorkerEditViewModel _viewModel;", + "lineNumber": 17 + }, + { + "text": " private bool _result;", + "lineNumber": 18 + }, + { + "lineNumber": 19 + }, + { + "text": " public WorkerEditWindow() : this(null)", + "lineNumber": 20 + }, + { + "text": " {", + "lineNumber": 21 + }, + { + "text": " }", + "lineNumber": 22 + }, + { + "lineNumber": 23 + }, + { + "text": " public WorkerEditWindow(WorkerConfig? worker)", + "lineNumber": 24 + }, + { + "text": " {", + "lineNumber": 25 + }, + { + "text": " InitializeComponent();", + "lineNumber": 26 + }, + { + "text": " var configService = new ConfigService();", + "lineNumber": 27 + }, + { + "text": " _viewModel = new WorkerEditViewModel(configService, worker);", + "lineNumber": 28 + }, + { + "text": " DataContext = _viewModel;", + "lineNumber": 29 + }, + { + "text": " SetupEventHandlers();", + "lineNumber": 30 + }, + { + "text": " }", + "lineNumber": 31 + }, + { + "lineNumber": 32 + }, + { + "text": " private void InitializeComponent()", + "lineNumber": 33 + }, + { + "text": " {", + "lineNumber": 34 + }, + { + "text": " Avalonia.Markup.Xaml.AvaloniaXamlLoader.Load(this);", + "lineNumber": 35 + }, + { + "text": " }", + "lineNumber": 36 + }, + { + "lineNumber": 37 + }, + { + "text": " private void SetupEventHandlers()", + "lineNumber": 38 + }, + { + "text": " {", + "lineNumber": 39 + }, + { + "text": " this.FindControl<Button>(\"OkButton\")!.Click += OkButton_Click;", + "lineNumber": 40 + }, + { + "text": " this.FindControl<Button>(\"CancelButton\")!.Click += CancelButton_Click;", + "lineNumber": 41 + }, + { + "text": " this.FindControl<Button>(\"AddDriveButton\")!.Click += AddDriveButton_Click;", + "lineNumber": 42 + }, + { + "text": " this.FindControl<Button>(\"RemoveDriveButton\")!.Click += RemoveDriveButton_Click;", + "lineNumber": 43 + }, + { + "text": " this.FindControl<Button>(\"AddPathButton\")!.Click += AddPathButton_Click;", + "lineNumber": 44 + }, + { + "text": " this.FindControl<Button>(\"RemovePathButton\")!.Click += RemovePathButton_Click;", + "lineNumber": 45 + }, + { + "text": " }", + "lineNumber": 46 + }, + { + "lineNumber": 47 + }, + { + "text": " private async void OkButton_Click(object? sender, RoutedEventArgs e)", + "lineNumber": 48 + }, + { + "text": " {", + "lineNumber": 49 + }, + { + "text": " if (string.IsNullOrWhiteSpace(_viewModel.Name))", + "lineNumber": 50 + } + ] + }, + "score": 0.31477874517440796 + }, + { + "codeBlock": { + "relativeWorkspacePath": ".\\Views\\WorkerEditWindow.axaml.cs", + "range": { + "startPosition": { + "line": 48 + }, + "endPosition": { + "line": 104 + } + }, + "contents": " {\n if (string.IsNullOrWhiteSpace(_viewModel.Name))\n {\n var box = MessageBoxManager.GetMessageBoxStandard(\"Error\", \n \"Worker name is required.\", \n ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Error);\n await box.ShowAsync();\n return;\n }\n\n try\n {\n _viewModel.Save();\n _result = true;\n Close();\n }\n catch (Exception ex)\n {\n var errorBox = MessageBoxManager.GetMessageBoxStandard(\"Error\", \n $\"Failed to save worker: {ex.Message}\", \n ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Error);\n await errorBox.ShowAsync();\n }\n }\n\n private void CancelButton_Click(object? sender, RoutedEventArgs e)\n {\n _result = false;\n Close();\n }\n\n private void AddDriveButton_Click(object? sender, RoutedEventArgs e)\n {\n // Simplified: use a simple input box\n // In a full implementation, you'd use a proper input dialog\n _viewModel.NetworkDrives.Add(\"A:\");\n }\n\n private void RemoveDriveButton_Click(object? sender, RoutedEventArgs e)\n {\n if (this.FindControl<ListBox>(\"NetworkDrivesListBox\")?.SelectedItem is string drive)\n {\n _viewModel.NetworkDrives.Remove(drive);\n }\n }\n\n private void AddPathButton_Click(object? sender, RoutedEventArgs e)\n {\n // Simplified: use a simple input box\n // In a full implementation, you'd use a proper input dialog\n _viewModel.NetworkPaths.Add(\"\\\\\\\\SERVER\\\\share\");\n }\n\n private void RemovePathButton_Click(object? sender, RoutedEventArgs e)\n {\n if (this.FindControl<ListBox>(\"NetworkPathsListBox\")?.SelectedItem is string path)", + "signatures": {}, + "detailedLines": [ + { + "text": " {", + "lineNumber": 49 + }, + { + "text": " if (string.IsNullOrWhiteSpace(_viewModel.Name))", + "lineNumber": 50 + }, + { + "text": " {", + "lineNumber": 51 + }, + { + "text": " var box = MessageBoxManager.GetMessageBoxStandard(\"Error\", ", + "lineNumber": 52 + }, + { + "text": " \"Worker name is required.\", ", + "lineNumber": 53 + }, + { + "text": " ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Error);", + "lineNumber": 54 + }, + { + "text": " await box.ShowAsync();", + "lineNumber": 55 + }, + { + "text": " return;", + "lineNumber": 56 + }, + { + "text": " }", + "lineNumber": 57 + }, + { + "lineNumber": 58 + }, + { + "text": " try", + "lineNumber": 59 + }, + { + "text": " {", + "lineNumber": 60 + }, + { + "text": " _viewModel.Save();", + "lineNumber": 61 + }, + { + "text": " _result = true;", + "lineNumber": 62 + }, + { + "text": " Close();", + "lineNumber": 63 + }, + { + "text": " }", + "lineNumber": 64 + }, + { + "text": " catch (Exception ex)", + "lineNumber": 65 + }, + { + "text": " {", + "lineNumber": 66 + }, + { + "text": " var errorBox = MessageBoxManager.GetMessageBoxStandard(\"Error\", ", + "lineNumber": 67 + }, + { + "text": " $\"Failed to save worker: {ex.Message}\", ", + "lineNumber": 68 + }, + { + "text": " ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Error);", + "lineNumber": 69 + }, + { + "text": " await errorBox.ShowAsync();", + "lineNumber": 70 + }, + { + "text": " }", + "lineNumber": 71 + }, + { + "text": " }", + "lineNumber": 72 + }, + { + "lineNumber": 73 + }, + { + "text": " private void CancelButton_Click(object? sender, RoutedEventArgs e)", + "lineNumber": 74 + }, + { + "text": " {", + "lineNumber": 75 + }, + { + "text": " _result = false;", + "lineNumber": 76 + }, + { + "text": " Close();", + "lineNumber": 77 + }, + { + "text": " }", + "lineNumber": 78 + }, + { + "lineNumber": 79 + }, + { + "text": " private void AddDriveButton_Click(object? sender, RoutedEventArgs e)", + "lineNumber": 80 + }, + { + "text": " {", + "lineNumber": 81 + }, + { + "text": " // Simplified: use a simple input box", + "lineNumber": 82 + }, + { + "text": " // In a full implementation, you'd use a proper input dialog", + "lineNumber": 83 + }, + { + "text": " _viewModel.NetworkDrives.Add(\"A:\");", + "lineNumber": 84 + }, + { + "text": " }", + "lineNumber": 85 + }, + { + "lineNumber": 86 + }, + { + "text": " private void RemoveDriveButton_Click(object? sender, RoutedEventArgs e)", + "lineNumber": 87 + }, + { + "text": " {", + "lineNumber": 88 + }, + { + "text": " if (this.FindControl<ListBox>(\"NetworkDrivesListBox\")?.SelectedItem is string drive)", + "lineNumber": 89 + }, + { + "text": " {", + "lineNumber": 90 + }, + { + "text": " _viewModel.NetworkDrives.Remove(drive);", + "lineNumber": 91 + }, + { + "text": " }", + "lineNumber": 92 + }, + { + "text": " }", + "lineNumber": 93 + }, + { + "lineNumber": 94 + }, + { + "text": " private void AddPathButton_Click(object? sender, RoutedEventArgs e)", + "lineNumber": 95 + }, + { + "text": " {", + "lineNumber": 96 + }, + { + "text": " // Simplified: use a simple input box", + "lineNumber": 97 + }, + { + "text": " // In a full implementation, you'd use a proper input dialog", + "lineNumber": 98 + }, + { + "text": " _viewModel.NetworkPaths.Add(\"\\\\\\\\SERVER\\\\share\");", + "lineNumber": 99 + }, + { + "text": " }", + "lineNumber": 100 + }, + { + "lineNumber": 101 + }, + { + "text": " private void RemovePathButton_Click(object? sender, RoutedEventArgs e)", + "lineNumber": 102 + }, + { + "text": " {", + "lineNumber": 103 + }, + { + "text": " if (this.FindControl<ListBox>(\"NetworkPathsListBox\")?.SelectedItem is string path)", + "lineNumber": 104 + } + ] + }, + "score": 0.30428460240364075 + }, + { + "codeBlock": { + "relativeWorkspacePath": ".\\Views\\MainWindow.axaml.cs", + "range": { + "startPosition": { + "line": 31 + }, + "endPosition": { + "line": 66 + } + }, + "contents": " }\n\n private void SetupEventHandlers()\n {\n this.FindControl<Button>(\"AddWorkerButton\")!.Click += AddWorkerButton_Click;\n this.FindControl<Button>(\"EditWorkerButton\")!.Click += EditWorkerButton_Click;\n this.FindControl<Button>(\"DeleteWorkerButton\")!.Click += DeleteWorkerButton_Click;\n this.FindControl<Button>(\"StartWorkerButton\")!.Click += StartWorkerButton_Click;\n this.FindControl<Button>(\"StopWorkerButton\")!.Click += StopWorkerButton_Click;\n this.FindControl<Button>(\"AttachWorkerButton\")!.Click += AttachWorkerButton_Click;\n this.FindControl<Button>(\"SettingsButton\")!.Click += SettingsButton_Click;\n this.FindControl<Button>(\"OperationModeToggleButton\")!.Click += OperationModeToggleButton_Click;\n this.FindControl<TabControl>(\"WorkerTypeTabs\")!.SelectionChanged += WorkerTypeTabs_SelectionChanged;\n this.FindControl<DataGrid>(\"WorkersGrid\")!.SelectionChanged += WorkersGrid_SelectionChanged;\n \n }\n\n private void OperationModeToggleButton_Click(object? sender, RoutedEventArgs e)\n {\n if (DataContext is MainWindowViewModel vm)\n {\n vm.OperationMode = vm.OperationMode == \"sheepit\" ? \"flamenco\" : \"sheepit\";\n }\n }\n\n private async void AddWorkerButton_Click(object? sender, RoutedEventArgs e)\n {\n var dialog = new WorkerEditWindow();\n if (await dialog.ShowDialogAsync(this))\n {\n ((MainWindowViewModel)DataContext!).RefreshWorkers();\n }\n }\n\n private async void EditWorkerButton_Click(object? sender, RoutedEventArgs e)", + "signatures": {}, + "detailedLines": [ + { + "text": " }", + "lineNumber": 32 + }, + { + "lineNumber": 33 + }, + { + "text": " private void SetupEventHandlers()", + "lineNumber": 34 + }, + { + "text": " {", + "lineNumber": 35 + }, + { + "text": " this.FindControl<Button>(\"AddWorkerButton\")!.Click += AddWorkerButton_Click;", + "lineNumber": 36 + }, + { + "text": " this.FindControl<Button>(\"EditWorkerButton\")!.Click += EditWorkerButton_Click;", + "lineNumber": 37 + }, + { + "text": " this.FindControl<Button>(\"DeleteWorkerButton\")!.Click += DeleteWorkerButton_Click;", + "lineNumber": 38 + }, + { + "text": " this.FindControl<Button>(\"StartWorkerButton\")!.Click += StartWorkerButton_Click;", + "lineNumber": 39 + }, + { + "text": " this.FindControl<Button>(\"StopWorkerButton\")!.Click += StopWorkerButton_Click;", + "lineNumber": 40 + }, + { + "text": " this.FindControl<Button>(\"AttachWorkerButton\")!.Click += AttachWorkerButton_Click;", + "lineNumber": 41 + }, + { + "text": " this.FindControl<Button>(\"SettingsButton\")!.Click += SettingsButton_Click;", + "lineNumber": 42 + }, + { + "text": " this.FindControl<Button>(\"OperationModeToggleButton\")!.Click += OperationModeToggleButton_Click;", + "lineNumber": 43 + }, + { + "text": " this.FindControl<TabControl>(\"WorkerTypeTabs\")!.SelectionChanged += WorkerTypeTabs_SelectionChanged;", + "lineNumber": 44 + }, + { + "text": " this.FindControl<DataGrid>(\"WorkersGrid\")!.SelectionChanged += WorkersGrid_SelectionChanged;", + "lineNumber": 45 + }, + { + "text": " ", + "lineNumber": 46 + }, + { + "text": " }", + "lineNumber": 47 + }, + { + "lineNumber": 48 + }, + { + "text": " private void OperationModeToggleButton_Click(object? sender, RoutedEventArgs e)", + "lineNumber": 49 + }, + { + "text": " {", + "lineNumber": 50 + }, + { + "text": " if (DataContext is MainWindowViewModel vm)", + "lineNumber": 51 + }, + { + "text": " {", + "lineNumber": 52 + }, + { + "text": " vm.OperationMode = vm.OperationMode == \"sheepit\" ? \"flamenco\" : \"sheepit\";", + "lineNumber": 53 + }, + { + "text": " }", + "lineNumber": 54 + }, + { + "text": " }", + "lineNumber": 55 + }, + { + "lineNumber": 56 + }, + { + "text": " private async void AddWorkerButton_Click(object? sender, RoutedEventArgs e)", + "lineNumber": 57 + }, + { + "text": " {", + "lineNumber": 58 + }, + { + "text": " var dialog = new WorkerEditWindow();", + "lineNumber": 59 + }, + { + "text": " if (await dialog.ShowDialogAsync(this))", + "lineNumber": 60 + }, + { + "text": " {", + "lineNumber": 61 + }, + { + "text": " ((MainWindowViewModel)DataContext!).RefreshWorkers();", + "lineNumber": 62 + }, + { + "text": " }", + "lineNumber": 63 + }, + { + "text": " }", + "lineNumber": 64 + }, + { + "lineNumber": 65 + }, + { + "text": " private async void EditWorkerButton_Click(object? sender, RoutedEventArgs e)", + "lineNumber": 66 + } + ] + }, + "score": 0.30311059951782227 + }, + { + "codeBlock": { + "relativeWorkspacePath": ".\\Views\\WorkerEditWindow.axaml", + "range": { + "startPosition": { + "line": 50 + }, + "endPosition": { + "line": 75 + } + }, + "contents": " </TabItem>\n\n <!-- Flamenco Tab -->\n <TabItem Header=\"Flamenco\">\n <StackPanel Margin=\"10\" Spacing=\"10\">\n <CheckBox Name=\"HasFlamencoCheckBox\" Content=\"Enable Flamenco Worker\" IsChecked=\"{Binding HasFlamenco}\" Margin=\"0,0,0,10\"/>\n \n <TextBlock Text=\"Note: Worker Path is configured in Global Settings.\" \n IsVisible=\"{Binding HasFlamenco}\" \n Margin=\"0,0,0,10\"\n Foreground=\"Gray\"\n TextWrapping=\"Wrap\"/>\n \n <TextBlock Text=\"Network Drives:\" IsVisible=\"{Binding HasFlamenco}\"/>\n <Grid IsVisible=\"{Binding HasFlamenco}\" RowDefinitions=\"*,Auto\" Margin=\"0,5,0,0\">\n <ListBox Name=\"NetworkDrivesListBox\" Grid.Row=\"0\" ItemsSource=\"{Binding NetworkDrives}\" MaxHeight=\"100\"/>\n <StackPanel Grid.Row=\"1\" Orientation=\"Horizontal\" Margin=\"0,5,0,0\">\n <Button Name=\"AddDriveButton\" Content=\"Add\" Width=\"60\" Margin=\"0,0,5,0\"/>\n <Button Name=\"RemoveDriveButton\" Content=\"Remove\" Width=\"60\"/>\n </StackPanel>\n </Grid>\n \n <TextBlock Text=\"Network Paths:\" IsVisible=\"{Binding HasFlamenco}\" Margin=\"0,10,0,0\"/>\n <Grid IsVisible=\"{Binding HasFlamenco}\" RowDefinitions=\"*,Auto\" Margin=\"0,5,0,0\">\n <ListBox Name=\"NetworkPathsListBox\" Grid.Row=\"0\" ItemsSource=\"{Binding NetworkPaths}\" MaxHeight=\"100\"/>", + "signatures": {}, + "detailedLines": [ + { + "text": " </TabItem>", + "lineNumber": 51 + }, + { + "lineNumber": 52 + }, + { + "text": " <!-- Flamenco Tab -->", + "lineNumber": 53 + }, + { + "text": " <TabItem Header=\"Flamenco\">", + "lineNumber": 54 + }, + { + "text": " <StackPanel Margin=\"10\" Spacing=\"10\">", + "lineNumber": 55 + }, + { + "text": " <CheckBox Name=\"HasFlamencoCheckBox\" Content=\"Enable Flamenco Worker\" IsChecked=\"{Binding HasFlamenco}\" Margin=\"0,0,0,10\"/>", + "lineNumber": 56 + }, + { + "text": " ", + "lineNumber": 57 + }, + { + "text": " <TextBlock Text=\"Note: Worker Path is configured in Global Settings.\" ", + "lineNumber": 58 + }, + { + "text": " IsVisible=\"{Binding HasFlamenco}\" ", + "lineNumber": 59 + }, + { + "text": " Margin=\"0,0,0,10\"", + "lineNumber": 60 + }, + { + "text": " Foreground=\"Gray\"", + "lineNumber": 61 + }, + { + "text": " TextWrapping=\"Wrap\"/>", + "lineNumber": 62 + }, + { + "text": " ", + "lineNumber": 63 + }, + { + "text": " <TextBlock Text=\"Network Drives:\" IsVisible=\"{Binding HasFlamenco}\"/>", + "lineNumber": 64 + }, + { + "text": " <Grid IsVisible=\"{Binding HasFlamenco}\" RowDefinitions=\"*,Auto\" Margin=\"0,5,0,0\">", + "lineNumber": 65 + }, + { + "text": " <ListBox Name=\"NetworkDrivesListBox\" Grid.Row=\"0\" ItemsSource=\"{Binding NetworkDrives}\" MaxHeight=\"100\"/>", + "lineNumber": 66 + }, + { + "text": " <StackPanel Grid.Row=\"1\" Orientation=\"Horizontal\" Margin=\"0,5,0,0\">", + "lineNumber": 67 + }, + { + "text": " <Button Name=\"AddDriveButton\" Content=\"Add\" Width=\"60\" Margin=\"0,0,5,0\"/>", + "lineNumber": 68 + }, + { + "text": " <Button Name=\"RemoveDriveButton\" Content=\"Remove\" Width=\"60\"/>", + "lineNumber": 69 + }, + { + "text": " </StackPanel>", + "lineNumber": 70 + }, + { + "text": " </Grid>", + "lineNumber": 71 + }, + { + "text": " ", + "lineNumber": 72 + }, + { + "text": " <TextBlock Text=\"Network Paths:\" IsVisible=\"{Binding HasFlamenco}\" Margin=\"0,10,0,0\"/>", + "lineNumber": 73 + }, + { + "text": " <Grid IsVisible=\"{Binding HasFlamenco}\" RowDefinitions=\"*,Auto\" Margin=\"0,5,0,0\">", + "lineNumber": 74 + }, + { + "text": " <ListBox Name=\"NetworkPathsListBox\" Grid.Row=\"0\" ItemsSource=\"{Binding NetworkPaths}\" MaxHeight=\"100\"/>", + "lineNumber": 75 + } + ] + }, + "score": 0.2986319065093994 + }, + { + "codeBlock": { + "relativeWorkspacePath": ".\\ViewModels\\GlobalSettingsViewModel.cs", + "range": { + "startPosition": {}, + "endPosition": { + "line": 61 + } + }, + "contents": "using UnifiedFarmLauncher.Models;\nusing UnifiedFarmLauncher.Services;\n\nnamespace UnifiedFarmLauncher.ViewModels\n{\n public class GlobalSettingsViewModel : ViewModelBase\n {\n private readonly ConfigService _configService;\n private string _sheepItUsername = string.Empty;\n private string _sheepItRenderKey = string.Empty;\n private bool _isRenderKeyVisible = false;\n private string _flamencoWorkerPath = string.Empty;\n\n public GlobalSettingsViewModel(ConfigService configService)\n {\n _configService = configService;\n LoadSettings();\n }\n\n public string SheepItUsername\n {\n get => _sheepItUsername;\n set => SetAndRaise(ref _sheepItUsername, value);\n }\n\n public string SheepItRenderKey\n {\n get => _sheepItRenderKey;\n set => SetAndRaise(ref _sheepItRenderKey, value);\n }\n\n public bool IsRenderKeyVisible\n {\n get => _isRenderKeyVisible;\n set => SetAndRaise(ref _isRenderKeyVisible, value);\n }\n\n public string FlamencoWorkerPath\n {\n get => _flamencoWorkerPath;\n set => SetAndRaise(ref _flamencoWorkerPath, value);\n }\n\n private void LoadSettings()\n {\n var config = _configService.Load();\n SheepItUsername = config.GlobalSettings.SheepItUsername;\n SheepItRenderKey = config.GlobalSettings.SheepItRenderKey;\n FlamencoWorkerPath = config.GlobalSettings.FlamencoWorkerPath;\n }\n\n public void Save()\n {\n var config = _configService.Load();\n config.GlobalSettings.SheepItUsername = SheepItUsername;\n config.GlobalSettings.SheepItRenderKey = SheepItRenderKey;\n config.GlobalSettings.FlamencoWorkerPath = FlamencoWorkerPath;\n _configService.Save(config);\n }\n }\n}", + "signatures": {}, + "detailedLines": [ + { + "text": "using UnifiedFarmLauncher.Models;", + "lineNumber": 1 + }, + { + "text": "using UnifiedFarmLauncher.Services;", + "lineNumber": 2 + }, + { + "lineNumber": 3 + }, + { + "text": "namespace UnifiedFarmLauncher.ViewModels", + "lineNumber": 4 + }, + { + "text": "{", + "lineNumber": 5 + }, + { + "text": " public class GlobalSettingsViewModel : ViewModelBase", + "lineNumber": 6 + }, + { + "text": " {", + "lineNumber": 7 + }, + { + "text": " private readonly ConfigService _configService;", + "lineNumber": 8 + }, + { + "text": " private string _sheepItUsername = string.Empty;", + "lineNumber": 9 + }, + { + "text": " private string _sheepItRenderKey = string.Empty;", + "lineNumber": 10 + }, + { + "text": " private bool _isRenderKeyVisible = false;", + "lineNumber": 11 + }, + { + "text": " private string _flamencoWorkerPath = string.Empty;", + "lineNumber": 12 + }, + { + "lineNumber": 13 + }, + { + "text": " public GlobalSettingsViewModel(ConfigService configService)", + "lineNumber": 14 + }, + { + "text": " {", + "lineNumber": 15 + }, + { + "text": " _configService = configService;", + "lineNumber": 16 + }, + { + "text": " LoadSettings();", + "lineNumber": 17 + }, + { + "text": " }", + "lineNumber": 18 + }, + { + "lineNumber": 19 + }, + { + "text": " public string SheepItUsername", + "lineNumber": 20 + }, + { + "text": " {", + "lineNumber": 21 + }, + { + "text": " get => _sheepItUsername;", + "lineNumber": 22 + }, + { + "text": " set => SetAndRaise(ref _sheepItUsername, value);", + "lineNumber": 23 + }, + { + "text": " }", + "lineNumber": 24 + }, + { + "lineNumber": 25 + }, + { + "text": " public string SheepItRenderKey", + "lineNumber": 26 + }, + { + "text": " {", + "lineNumber": 27 + }, + { + "text": " get => _sheepItRenderKey;", + "lineNumber": 28 + }, + { + "text": " set => SetAndRaise(ref _sheepItRenderKey, value);", + "lineNumber": 29 + }, + { + "text": " }", + "lineNumber": 30 + }, + { + "lineNumber": 31 + }, + { + "text": " public bool IsRenderKeyVisible", + "lineNumber": 32 + }, + { + "text": " {", + "lineNumber": 33 + }, + { + "text": " get => _isRenderKeyVisible;", + "lineNumber": 34 + }, + { + "text": " set => SetAndRaise(ref _isRenderKeyVisible, value);", + "lineNumber": 35 + }, + { + "text": " }", + "lineNumber": 36 + }, + { + "lineNumber": 37 + }, + { + "text": " public string FlamencoWorkerPath", + "lineNumber": 38 + }, + { + "text": " {", + "lineNumber": 39 + }, + { + "text": " get => _flamencoWorkerPath;", + "lineNumber": 40 + }, + { + "text": " set => SetAndRaise(ref _flamencoWorkerPath, value);", + "lineNumber": 41 + }, + { + "text": " }", + "lineNumber": 42 + }, + { + "lineNumber": 43 + }, + { + "text": " private void LoadSettings()", + "lineNumber": 44 + }, + { + "text": " {", + "lineNumber": 45 + }, + { + "text": " var config = _configService.Load();", + "lineNumber": 46 + }, + { + "text": " SheepItUsername = config.GlobalSettings.SheepItUsername;", + "lineNumber": 47 + }, + { + "text": " SheepItRenderKey = config.GlobalSettings.SheepItRenderKey;", + "lineNumber": 48 + }, + { + "text": " FlamencoWorkerPath = config.GlobalSettings.FlamencoWorkerPath;", + "lineNumber": 49 + }, + { + "text": " }", + "lineNumber": 50 + }, + { + "lineNumber": 51 + }, + { + "text": " public void Save()", + "lineNumber": 52 + }, + { + "text": " {", + "lineNumber": 53 + }, + { + "text": " var config = _configService.Load();", + "lineNumber": 54 + }, + { + "text": " config.GlobalSettings.SheepItUsername = SheepItUsername;", + "lineNumber": 55 + }, + { + "text": " config.GlobalSettings.SheepItRenderKey = SheepItRenderKey;", + "lineNumber": 56 + }, + { + "text": " config.GlobalSettings.FlamencoWorkerPath = FlamencoWorkerPath;", + "lineNumber": 57 + }, + { + "text": " _configService.Save(config);", + "lineNumber": 58 + }, + { + "text": " }", + "lineNumber": 59 + }, + { + "text": " }", + "lineNumber": 60 + }, + { + "text": "}", + "lineNumber": 61 + } + ] + }, + "score": 0.2920593023300171 + }, + { + "codeBlock": { + "relativeWorkspacePath": ".\\Views\\MainWindow.axaml.cs", + "range": { + "startPosition": { + "line": 209 + }, + "endPosition": { + "line": 246 + } + }, + "contents": " }\n catch (System.Exception ex)\n {\n var errorBox = MessageBoxManager.GetMessageBoxStandard(\"Error\", \n $\"Failed to attach to worker: {ex.Message}\", \n ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Error);\n await errorBox.ShowAsync();\n }\n }\n }\n\n private void WorkerTypeTabs_SelectionChanged(object? sender, SelectionChangedEventArgs e)\n {\n if (this.FindControl<TabControl>(\"WorkerTypeTabs\")?.SelectedItem is TabItem tab)\n {\n var type = tab.Header?.ToString() ?? \"All\";\n if (type == \"All Workers\") type = \"All\";\n ((MainWindowViewModel)DataContext!).SelectedWorkerType = type;\n }\n }\n\n private async void SettingsButton_Click(object? sender, RoutedEventArgs e)\n {\n var dialog = new GlobalSettingsWindow();\n await dialog.ShowDialogAsync(this);\n }\n\n private void WorkersGrid_SelectionChanged(object? sender, SelectionChangedEventArgs e)\n {\n if (DataContext is MainWindowViewModel vm)\n {\n vm.SelectedWorker = this.FindControl<DataGrid>(\"WorkersGrid\")?.SelectedItem as WorkerConfig;\n }\n }\n }\n}", + "signatures": {}, + "detailedLines": [ + { + "text": " }", + "lineNumber": 210 + }, + { + "text": " catch (System.Exception ex)", + "lineNumber": 211 + }, + { + "text": " {", + "lineNumber": 212 + }, + { + "text": " var errorBox = MessageBoxManager.GetMessageBoxStandard(\"Error\", ", + "lineNumber": 213 + }, + { + "text": " $\"Failed to attach to worker: {ex.Message}\", ", + "lineNumber": 214 + }, + { + "text": " ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Error);", + "lineNumber": 215 + }, + { + "text": " await errorBox.ShowAsync();", + "lineNumber": 216 + }, + { + "text": " }", + "lineNumber": 217 + }, + { + "text": " }", + "lineNumber": 218 + }, + { + "text": " }", + "lineNumber": 219 + }, + { + "lineNumber": 220 + }, + { + "text": " private void WorkerTypeTabs_SelectionChanged(object? sender, SelectionChangedEventArgs e)", + "lineNumber": 221 + }, + { + "text": " {", + "lineNumber": 222 + }, + { + "text": " if (this.FindControl<TabControl>(\"WorkerTypeTabs\")?.SelectedItem is TabItem tab)", + "lineNumber": 223 + }, + { + "text": " {", + "lineNumber": 224 + }, + { + "text": " var type = tab.Header?.ToString() ?? \"All\";", + "lineNumber": 225 + }, + { + "text": " if (type == \"All Workers\") type = \"All\";", + "lineNumber": 226 + }, + { + "text": " ((MainWindowViewModel)DataContext!).SelectedWorkerType = type;", + "lineNumber": 227 + }, + { + "text": " }", + "lineNumber": 228 + }, + { + "text": " }", + "lineNumber": 229 + }, + { + "lineNumber": 230 + }, + { + "text": " private async void SettingsButton_Click(object? sender, RoutedEventArgs e)", + "lineNumber": 231 + }, + { + "text": " {", + "lineNumber": 232 + }, + { + "text": " var dialog = new GlobalSettingsWindow();", + "lineNumber": 233 + }, + { + "text": " await dialog.ShowDialogAsync(this);", + "lineNumber": 234 + }, + { + "text": " }", + "lineNumber": 235 + }, + { + "lineNumber": 236 + }, + { + "text": " private void WorkersGrid_SelectionChanged(object? sender, SelectionChangedEventArgs e)", + "lineNumber": 237 + }, + { + "text": " {", + "lineNumber": 238 + }, + { + "text": " if (DataContext is MainWindowViewModel vm)", + "lineNumber": 239 + }, + { + "text": " {", + "lineNumber": 240 + }, + { + "text": " vm.SelectedWorker = this.FindControl<DataGrid>(\"WorkersGrid\")?.SelectedItem as WorkerConfig;", + "lineNumber": 241 + }, + { + "text": " }", + "lineNumber": 242 + }, + { + "text": " }", + "lineNumber": 243 + }, + { + "text": " }", + "lineNumber": 244 + }, + { + "text": "}", + "lineNumber": 245 + } + ] + }, + "score": 0.27719610929489136 + }, + { + "codeBlock": { + "relativeWorkspacePath": ".\\ViewModels\\MainWindowViewModel.cs", + "range": { + "startPosition": { + "line": 52 + }, + "endPosition": { + "line": 119 + } + }, + "contents": " }\n }\n\n public string OperationMode\n {\n get => _operationMode;\n set\n {\n if (SetAndRaise(ref _operationMode, value))\n {\n // Notify that dependent properties also changed\n OnPropertyChanged(nameof(OperationModeDisplayName));\n OnPropertyChanged(nameof(OperationModeIcon));\n }\n }\n }\n\n public string OperationModeDisplayName => OperationMode == \"sheepit\" ? \"SheepIt\" : \"Flamenco\";\n \n public string OperationModeIcon => OperationMode == \"sheepit\" ? \"🐑\" : \"🔥\";\n\n public void LoadWorkers()\n {\n _configService.Reload();\n var config = _configService.Load();\n Workers.Clear();\n\n var workers = config.Workers;\n if (SelectedWorkerType != \"All\")\n {\n workers = workers.Where(w =>\n {\n if (SelectedWorkerType == \"SheepIt\")\n return w.WorkerTypes.SheepIt != null;\n if (SelectedWorkerType == \"Flamenco\")\n return w.WorkerTypes.Flamenco != null;\n return true;\n }).ToList();\n }\n\n foreach (var worker in workers)\n {\n Workers.Add(worker);\n }\n\n UpdateStatusText();\n }\n\n private void UpdateStatusText()\n {\n if (SelectedWorker == null)\n {\n StatusText = $\"Total workers: {Workers.Count}\";\n }\n else\n {\n StatusText = $\"Selected: {SelectedWorker.Name} ({SelectedWorker.Ssh.Host}:{SelectedWorker.Ssh.Port})\";\n }\n }\n\n public void RefreshWorkers()\n {\n LoadWorkers();\n }\n }\n}", + "signatures": {}, + "detailedLines": [ + { + "text": " }", + "lineNumber": 53 + }, + { + "text": " }", + "lineNumber": 54 + }, + { + "lineNumber": 55 + }, + { + "text": " public string OperationMode", + "lineNumber": 56 + }, + { + "text": " {", + "lineNumber": 57 + }, + { + "text": " get => _operationMode;", + "lineNumber": 58 + }, + { + "text": " set", + "lineNumber": 59 + }, + { + "text": " {", + "lineNumber": 60 + }, + { + "text": " if (SetAndRaise(ref _operationMode, value))", + "lineNumber": 61 + }, + { + "text": " {", + "lineNumber": 62 + }, + { + "text": " // Notify that dependent properties also changed", + "lineNumber": 63 + }, + { + "text": " OnPropertyChanged(nameof(OperationModeDisplayName));", + "lineNumber": 64 + }, + { + "text": " OnPropertyChanged(nameof(OperationModeIcon));", + "lineNumber": 65 + }, + { + "text": " }", + "lineNumber": 66 + }, + { + "text": " }", + "lineNumber": 67 + }, + { + "text": " }", + "lineNumber": 68 + }, + { + "lineNumber": 69 + }, + { + "text": " public string OperationModeDisplayName => OperationMode == \"sheepit\" ? \"SheepIt\" : \"Flamenco\";", + "lineNumber": 70 + }, + { + "text": " ", + "lineNumber": 71 + }, + { + "text": " public string OperationModeIcon => OperationMode == \"sheepit\" ? \"🐑\" : \"🔥\";", + "lineNumber": 72 + }, + { + "lineNumber": 73 + }, + { + "text": " public void LoadWorkers()", + "lineNumber": 74 + }, + { + "text": " {", + "lineNumber": 75 + }, + { + "text": " _configService.Reload();", + "lineNumber": 76 + }, + { + "text": " var config = _configService.Load();", + "lineNumber": 77 + }, + { + "text": " Workers.Clear();", + "lineNumber": 78 + }, + { + "lineNumber": 79 + }, + { + "text": " var workers = config.Workers;", + "lineNumber": 80 + }, + { + "text": " if (SelectedWorkerType != \"All\")", + "lineNumber": 81 + }, + { + "text": " {", + "lineNumber": 82 + }, + { + "text": " workers = workers.Where(w =>", + "lineNumber": 83 + }, + { + "text": " {", + "lineNumber": 84 + }, + { + "text": " if (SelectedWorkerType == \"SheepIt\")", + "lineNumber": 85 + }, + { + "text": " return w.WorkerTypes.SheepIt != null;", + "lineNumber": 86 + }, + { + "text": " if (SelectedWorkerType == \"Flamenco\")", + "lineNumber": 87 + }, + { + "text": " return w.WorkerTypes.Flamenco != null;", + "lineNumber": 88 + }, + { + "text": " return true;", + "lineNumber": 89 + }, + { + "text": " }).ToList();", + "lineNumber": 90 + }, + { + "text": " }", + "lineNumber": 91 + }, + { + "lineNumber": 92 + }, + { + "text": " foreach (var worker in workers)", + "lineNumber": 93 + }, + { + "text": " {", + "lineNumber": 94 + }, + { + "text": " Workers.Add(worker);", + "lineNumber": 95 + }, + { + "text": " }", + "lineNumber": 96 + }, + { + "lineNumber": 97 + }, + { + "text": " UpdateStatusText();", + "lineNumber": 98 + }, + { + "text": " }", + "lineNumber": 99 + }, + { + "lineNumber": 100 + }, + { + "text": " private void UpdateStatusText()", + "lineNumber": 101 + }, + { + "text": " {", + "lineNumber": 102 + }, + { + "text": " if (SelectedWorker == null)", + "lineNumber": 103 + }, + { + "text": " {", + "lineNumber": 104 + }, + { + "text": " StatusText = $\"Total workers: {Workers.Count}\";", + "lineNumber": 105 + }, + { + "text": " }", + "lineNumber": 106 + }, + { + "text": " else", + "lineNumber": 107 + }, + { + "text": " {", + "lineNumber": 108 + }, + { + "text": " StatusText = $\"Selected: {SelectedWorker.Name} ({SelectedWorker.Ssh.Host}:{SelectedWorker.Ssh.Port})\";", + "lineNumber": 109 + }, + { + "text": " }", + "lineNumber": 110 + }, + { + "text": " }", + "lineNumber": 111 + }, + { + "lineNumber": 112 + }, + { + "text": " public void RefreshWorkers()", + "lineNumber": 113 + }, + { + "text": " {", + "lineNumber": 114 + }, + { + "text": " LoadWorkers();", + "lineNumber": 115 + }, + { + "text": " }", + "lineNumber": 116 + }, + { + "text": " }", + "lineNumber": 117 + }, + { + "text": "}", + "lineNumber": 118 + } + ] + }, + "score": 0.26766306161880493 + }, + { + "codeBlock": { + "relativeWorkspacePath": ".\\Views\\MainWindow.axaml.cs", + "range": { + "startPosition": { + "line": 62 + }, + "endPosition": { + "line": 104 + } + }, + "contents": " }\n }\n\n private async void EditWorkerButton_Click(object? sender, RoutedEventArgs e)\n {\n if (this.FindControl<DataGrid>(\"WorkersGrid\")?.SelectedItem is WorkerConfig worker)\n {\n var dialog = new WorkerEditWindow(worker);\n if (await dialog.ShowDialogAsync(this))\n {\n ((MainWindowViewModel)DataContext!).RefreshWorkers();\n }\n }\n }\n\n private async void DeleteWorkerButton_Click(object? sender, RoutedEventArgs e)\n {\n if (this.FindControl<DataGrid>(\"WorkersGrid\")?.SelectedItem is WorkerConfig worker)\n {\n var box = MessageBoxManager.GetMessageBoxStandard(\"Delete Worker\", \n $\"Are you sure you want to delete worker '{worker.Name}'?\", \n ButtonEnum.YesNo, MsBox.Avalonia.Enums.Icon.Warning);\n var result = await box.ShowAsync();\n \n if (result == ButtonResult.Yes)\n {\n _configService.DeleteWorker(worker.Id);\n ((MainWindowViewModel)DataContext!).RefreshWorkers();\n }\n }\n }\n\n private async void StartWorkerButton_Click(object? sender, RoutedEventArgs e)\n {\n if (this.FindControl<DataGrid>(\"WorkersGrid\")?.SelectedItem is WorkerConfig worker)\n {\n try\n {\n var vm = (MainWindowViewModel)DataContext!;\n string? workerType = vm.OperationMode;\n\n // Verify the worker supports the selected operation mode", + "signatures": {}, + "detailedLines": [ + { + "text": " }", + "lineNumber": 63 + }, + { + "text": " }", + "lineNumber": 64 + }, + { + "lineNumber": 65 + }, + { + "text": " private async void EditWorkerButton_Click(object? sender, RoutedEventArgs e)", + "lineNumber": 66 + }, + { + "text": " {", + "lineNumber": 67 + }, + { + "text": " if (this.FindControl<DataGrid>(\"WorkersGrid\")?.SelectedItem is WorkerConfig worker)", + "lineNumber": 68 + }, + { + "text": " {", + "lineNumber": 69 + }, + { + "text": " var dialog = new WorkerEditWindow(worker);", + "lineNumber": 70 + }, + { + "text": " if (await dialog.ShowDialogAsync(this))", + "lineNumber": 71 + }, + { + "text": " {", + "lineNumber": 72 + }, + { + "text": " ((MainWindowViewModel)DataContext!).RefreshWorkers();", + "lineNumber": 73 + }, + { + "text": " }", + "lineNumber": 74 + }, + { + "text": " }", + "lineNumber": 75 + }, + { + "text": " }", + "lineNumber": 76 + }, + { + "lineNumber": 77 + }, + { + "text": " private async void DeleteWorkerButton_Click(object? sender, RoutedEventArgs e)", + "lineNumber": 78 + }, + { + "text": " {", + "lineNumber": 79 + }, + { + "text": " if (this.FindControl<DataGrid>(\"WorkersGrid\")?.SelectedItem is WorkerConfig worker)", + "lineNumber": 80 + }, + { + "text": " {", + "lineNumber": 81 + }, + { + "text": " var box = MessageBoxManager.GetMessageBoxStandard(\"Delete Worker\", ", + "lineNumber": 82 + }, + { + "text": " $\"Are you sure you want to delete worker '{worker.Name}'?\", ", + "lineNumber": 83 + }, + { + "text": " ButtonEnum.YesNo, MsBox.Avalonia.Enums.Icon.Warning);", + "lineNumber": 84 + }, + { + "text": " var result = await box.ShowAsync();", + "lineNumber": 85 + }, + { + "text": " ", + "lineNumber": 86 + }, + { + "text": " if (result == ButtonResult.Yes)", + "lineNumber": 87 + }, + { + "text": " {", + "lineNumber": 88 + }, + { + "text": " _configService.DeleteWorker(worker.Id);", + "lineNumber": 89 + }, + { + "text": " ((MainWindowViewModel)DataContext!).RefreshWorkers();", + "lineNumber": 90 + }, + { + "text": " }", + "lineNumber": 91 + }, + { + "text": " }", + "lineNumber": 92 + }, + { + "text": " }", + "lineNumber": 93 + }, + { + "lineNumber": 94 + }, + { + "text": " private async void StartWorkerButton_Click(object? sender, RoutedEventArgs e)", + "lineNumber": 95 + }, + { + "text": " {", + "lineNumber": 96 + }, + { + "text": " if (this.FindControl<DataGrid>(\"WorkersGrid\")?.SelectedItem is WorkerConfig worker)", + "lineNumber": 97 + }, + { + "text": " {", + "lineNumber": 98 + }, + { + "text": " try", + "lineNumber": 99 + }, + { + "text": " {", + "lineNumber": 100 + }, + { + "text": " var vm = (MainWindowViewModel)DataContext!;", + "lineNumber": 101 + }, + { + "text": " string? workerType = vm.OperationMode;", + "lineNumber": 102 + }, + { + "lineNumber": 103 + }, + { + "text": " // Verify the worker supports the selected operation mode", + "lineNumber": 104 + } + ] + }, + "score": 0.26550209522247314 + }, + { + "codeBlock": { + "relativeWorkspacePath": ".\\Views\\MainWindow.axaml", + "range": { + "startPosition": { + "line": 33 + }, + "endPosition": { + "line": 73, + "column": 12 + } + }, + "contents": " MinWidth=\"120\">\n <StackPanel Orientation=\"Horizontal\" Spacing=\"5\">\n <TextBlock Text=\"{Binding OperationModeIcon}\" FontSize=\"16\" VerticalAlignment=\"Center\"/>\n <TextBlock Text=\"{Binding OperationModeDisplayName}\" \n VerticalAlignment=\"Center\" FontWeight=\"Bold\"/>\n </StackPanel>\n </Button>\n </Grid>\n\n <!-- Worker Type Filter -->\n <TabControl Name=\"WorkerTypeTabs\" Grid.Row=\"1\" Margin=\"5,0\">\n <TabItem Header=\"All Workers\">\n <TextBlock Text=\"All Workers\" IsVisible=\"False\"/>\n </TabItem>\n <TabItem Header=\"SheepIt\">\n <TextBlock Text=\"SheepIt\" IsVisible=\"False\"/>\n </TabItem>\n <TabItem Header=\"Flamenco\">\n <TextBlock Text=\"Flamenco\" IsVisible=\"False\"/>\n </TabItem>\n </TabControl>\n\n <!-- Worker List -->\n <DataGrid Name=\"WorkersGrid\" Grid.Row=\"2\" Margin=\"5\"\n AutoGenerateColumns=\"False\"\n IsReadOnly=\"True\"\n SelectionMode=\"Single\"\n GridLinesVisibility=\"All\"\n ItemsSource=\"{Binding Workers}\">\n <DataGrid.Columns>\n <DataGridTextColumn Header=\"Name\" Binding=\"{Binding Name}\" Width=\"150\"/>\n <DataGridCheckBoxColumn Header=\"Enabled\" Binding=\"{Binding Enabled}\" Width=\"80\"/>\n <DataGridTextColumn Header=\"SSH Host\" Binding=\"{Binding Ssh.Host}\" Width=\"150\"/>\n <DataGridTextColumn Header=\"SSH Port\" Binding=\"{Binding Ssh.Port}\" Width=\"80\"/>\n <DataGridTextColumn Header=\"Worker Types\" Binding=\"{Binding WorkerTypes}\" Width=\"*\"/>\n </DataGrid.Columns>\n </DataGrid>\n\n <!-- Status Bar -->\n <Border Grid.Row=\"3\" Background=\"{DynamicResource ThemeControlLowBackgroundBrush}\" BorderBrush=\"{DynamicResource ThemeBorderLowBrush}\" BorderThickness=\"0,1,0,0\">\n ", + "signatures": {}, + "detailedLines": [ + { + "text": " MinWidth=\"120\">", + "lineNumber": 34 + }, + { + "text": " <StackPanel Orientation=\"Horizontal\" Spacing=\"5\">", + "lineNumber": 35 + }, + { + "text": " <TextBlock Text=\"{Binding OperationModeIcon}\" FontSize=\"16\" VerticalAlignment=\"Center\"/>", + "lineNumber": 36 + }, + { + "text": " <TextBlock Text=\"{Binding OperationModeDisplayName}\" ", + "lineNumber": 37 + }, + { + "text": " VerticalAlignment=\"Center\" FontWeight=\"Bold\"/>", + "lineNumber": 38 + }, + { + "text": " </StackPanel>", + "lineNumber": 39 + }, + { + "text": " </Button>", + "lineNumber": 40 + }, + { + "text": " </Grid>", + "lineNumber": 41 + }, + { + "lineNumber": 42 + }, + { + "text": " <!-- Worker Type Filter -->", + "lineNumber": 43 + }, + { + "text": " <TabControl Name=\"WorkerTypeTabs\" Grid.Row=\"1\" Margin=\"5,0\">", + "lineNumber": 44 + }, + { + "text": " <TabItem Header=\"All Workers\">", + "lineNumber": 45 + }, + { + "text": " <TextBlock Text=\"All Workers\" IsVisible=\"False\"/>", + "lineNumber": 46 + }, + { + "text": " </TabItem>", + "lineNumber": 47 + }, + { + "text": " <TabItem Header=\"SheepIt\">", + "lineNumber": 48 + }, + { + "text": " <TextBlock Text=\"SheepIt\" IsVisible=\"False\"/>", + "lineNumber": 49 + }, + { + "text": " </TabItem>", + "lineNumber": 50 + }, + { + "text": " <TabItem Header=\"Flamenco\">", + "lineNumber": 51 + }, + { + "text": " <TextBlock Text=\"Flamenco\" IsVisible=\"False\"/>", + "lineNumber": 52 + }, + { + "text": " </TabItem>", + "lineNumber": 53 + }, + { + "text": " </TabControl>", + "lineNumber": 54 + }, + { + "lineNumber": 55 + }, + { + "text": " <!-- Worker List -->", + "lineNumber": 56 + }, + { + "text": " <DataGrid Name=\"WorkersGrid\" Grid.Row=\"2\" Margin=\"5\"", + "lineNumber": 57 + }, + { + "text": " AutoGenerateColumns=\"False\"", + "lineNumber": 58 + }, + { + "text": " IsReadOnly=\"True\"", + "lineNumber": 59 + }, + { + "text": " SelectionMode=\"Single\"", + "lineNumber": 60 + }, + { + "text": " GridLinesVisibility=\"All\"", + "lineNumber": 61 + }, + { + "text": " ItemsSource=\"{Binding Workers}\">", + "lineNumber": 62 + }, + { + "text": " <DataGrid.Columns>", + "lineNumber": 63 + }, + { + "text": " <DataGridTextColumn Header=\"Name\" Binding=\"{Binding Name}\" Width=\"150\"/>", + "lineNumber": 64 + }, + { + "text": " <DataGridCheckBoxColumn Header=\"Enabled\" Binding=\"{Binding Enabled}\" Width=\"80\"/>", + "lineNumber": 65 + }, + { + "text": " <DataGridTextColumn Header=\"SSH Host\" Binding=\"{Binding Ssh.Host}\" Width=\"150\"/>", + "lineNumber": 66 + }, + { + "text": " <DataGridTextColumn Header=\"SSH Port\" Binding=\"{Binding Ssh.Port}\" Width=\"80\"/>", + "lineNumber": 67 + }, + { + "text": " <DataGridTextColumn Header=\"Worker Types\" Binding=\"{Binding WorkerTypes}\" Width=\"*\"/>", + "lineNumber": 68 + }, + { + "text": " </DataGrid.Columns>", + "lineNumber": 69 + }, + { + "text": " </DataGrid>", + "lineNumber": 70 + }, + { + "lineNumber": 71 + }, + { + "text": " <!-- Status Bar -->", + "lineNumber": 72 + }, + { + "text": " <Border Grid.Row=\"3\" Background=\"{DynamicResource ThemeControlLowBackgroundBrush}\" BorderBrush=\"{DynamicResource ThemeBorderLowBrush}\" BorderThickness=\"0,1,0,0\">", + "lineNumber": 73 + }, + { + "text": " ", + "lineNumber": 74 + } + ] + }, + "score": 0.2587176561355591 + }, + { + "codeBlock": { + "relativeWorkspacePath": ".\\Views\\WorkerEditWindow.axaml", + "range": { + "startPosition": { + "line": 73 + }, + "endPosition": { + "line": 92 + } + }, + "contents": " <Grid IsVisible=\"{Binding HasFlamenco}\" RowDefinitions=\"*,Auto\" Margin=\"0,5,0,0\">\n <ListBox Name=\"NetworkPathsListBox\" Grid.Row=\"0\" ItemsSource=\"{Binding NetworkPaths}\" MaxHeight=\"100\"/>\n <StackPanel Grid.Row=\"1\" Orientation=\"Horizontal\" Margin=\"0,5,0,0\">\n <Button Name=\"AddPathButton\" Content=\"Add\" Width=\"60\" Margin=\"0,0,5,0\"/>\n <Button Name=\"RemovePathButton\" Content=\"Remove\" Width=\"60\"/>\n </StackPanel>\n </Grid>\n </StackPanel>\n </TabItem>\n </TabControl>\n\n <!-- Buttons -->\n <StackPanel Orientation=\"Horizontal\" HorizontalAlignment=\"Right\" Grid.Row=\"2\" Spacing=\"10\" Margin=\"0,10,0,0\">\n <Button Name=\"OkButton\" Content=\"OK\" Width=\"80\" IsDefault=\"True\"/>\n <Button Name=\"CancelButton\" Content=\"Cancel\" Width=\"80\" IsCancel=\"True\"/>\n </StackPanel>\n </Grid>\n</Window>", + "signatures": {}, + "detailedLines": [ + { + "text": " <Grid IsVisible=\"{Binding HasFlamenco}\" RowDefinitions=\"*,Auto\" Margin=\"0,5,0,0\">", + "lineNumber": 74 + }, + { + "text": " <ListBox Name=\"NetworkPathsListBox\" Grid.Row=\"0\" ItemsSource=\"{Binding NetworkPaths}\" MaxHeight=\"100\"/>", + "lineNumber": 75 + }, + { + "text": " <StackPanel Grid.Row=\"1\" Orientation=\"Horizontal\" Margin=\"0,5,0,0\">", + "lineNumber": 76 + }, + { + "text": " <Button Name=\"AddPathButton\" Content=\"Add\" Width=\"60\" Margin=\"0,0,5,0\"/>", + "lineNumber": 77 + }, + { + "text": " <Button Name=\"RemovePathButton\" Content=\"Remove\" Width=\"60\"/>", + "lineNumber": 78 + }, + { + "text": " </StackPanel>", + "lineNumber": 79 + }, + { + "text": " </Grid>", + "lineNumber": 80 + }, + { + "text": " </StackPanel>", + "lineNumber": 81 + }, + { + "text": " </TabItem>", + "lineNumber": 82 + }, + { + "text": " </TabControl>", + "lineNumber": 83 + }, + { + "lineNumber": 84 + }, + { + "text": " <!-- Buttons -->", + "lineNumber": 85 + }, + { + "text": " <StackPanel Orientation=\"Horizontal\" HorizontalAlignment=\"Right\" Grid.Row=\"2\" Spacing=\"10\" Margin=\"0,10,0,0\">", + "lineNumber": 86 + }, + { + "text": " <Button Name=\"OkButton\" Content=\"OK\" Width=\"80\" IsDefault=\"True\"/>", + "lineNumber": 87 + }, + { + "text": " <Button Name=\"CancelButton\" Content=\"Cancel\" Width=\"80\" IsCancel=\"True\"/>", + "lineNumber": 88 + }, + { + "text": " </StackPanel>", + "lineNumber": 89 + }, + { + "text": " </Grid>", + "lineNumber": 90 + }, + { + "text": "</Window>", + "lineNumber": 91 + } + ] + }, + "score": 0.2566637396812439 + }, + { + "codeBlock": { + "relativeWorkspacePath": ".\\ViewModels\\MainWindowViewModel.cs", + "range": { + "startPosition": {}, + "endPosition": { + "line": 56 + } + }, + "contents": "using System.Collections.ObjectModel;\nusing System.Linq;\nusing System.Threading.Tasks;\nusing UnifiedFarmLauncher.Models;\nusing UnifiedFarmLauncher.Services;\n\nnamespace UnifiedFarmLauncher.ViewModels\n{\n public class MainWindowViewModel : ViewModelBase\n {\n private readonly ConfigService _configService;\n private WorkerConfig? _selectedWorker;\n private string _statusText = \"Ready\";\n private string _selectedWorkerType = \"All\";\n private string _operationMode = \"sheepit\"; // \"sheepit\" or \"flamenco\"\n\n public MainWindowViewModel()\n {\n _configService = new ConfigService();\n Workers = new ObservableCollection<WorkerConfig>();\n LoadWorkers();\n }\n\n public ObservableCollection<WorkerConfig> Workers { get; }\n\n public WorkerConfig? SelectedWorker\n {\n get => _selectedWorker;\n set\n {\n if (SetAndRaise(ref _selectedWorker, value))\n {\n UpdateStatusText();\n }\n }\n }\n\n public string StatusText\n {\n get => _statusText;\n set => SetAndRaise(ref _statusText, value);\n }\n\n public string SelectedWorkerType\n {\n get => _selectedWorkerType;\n set\n {\n if (SetAndRaise(ref _selectedWorkerType, value))\n {\n LoadWorkers();\n }\n }\n }\n\n public string OperationMode", + "signatures": {}, + "detailedLines": [ + { + "text": "using System.Collections.ObjectModel;", + "lineNumber": 1 + }, + { + "text": "using System.Linq;", + "lineNumber": 2 + }, + { + "text": "using System.Threading.Tasks;", + "lineNumber": 3 + }, + { + "text": "using UnifiedFarmLauncher.Models;", + "lineNumber": 4 + }, + { + "text": "using UnifiedFarmLauncher.Services;", + "lineNumber": 5 + }, + { + "lineNumber": 6 + }, + { + "text": "namespace UnifiedFarmLauncher.ViewModels", + "lineNumber": 7 + }, + { + "text": "{", + "lineNumber": 8 + }, + { + "text": " public class MainWindowViewModel : ViewModelBase", + "lineNumber": 9 + }, + { + "text": " {", + "lineNumber": 10 + }, + { + "text": " private readonly ConfigService _configService;", + "lineNumber": 11 + }, + { + "text": " private WorkerConfig? _selectedWorker;", + "lineNumber": 12 + }, + { + "text": " private string _statusText = \"Ready\";", + "lineNumber": 13 + }, + { + "text": " private string _selectedWorkerType = \"All\";", + "lineNumber": 14 + }, + { + "text": " private string _operationMode = \"sheepit\"; // \"sheepit\" or \"flamenco\"", + "lineNumber": 15 + }, + { + "lineNumber": 16 + }, + { + "text": " public MainWindowViewModel()", + "lineNumber": 17 + }, + { + "text": " {", + "lineNumber": 18 + }, + { + "text": " _configService = new ConfigService();", + "lineNumber": 19 + }, + { + "text": " Workers = new ObservableCollection<WorkerConfig>();", + "lineNumber": 20 + }, + { + "text": " LoadWorkers();", + "lineNumber": 21 + }, + { + "text": " }", + "lineNumber": 22 + }, + { + "lineNumber": 23 + }, + { + "text": " public ObservableCollection<WorkerConfig> Workers { get; }", + "lineNumber": 24 + }, + { + "lineNumber": 25 + }, + { + "text": " public WorkerConfig? SelectedWorker", + "lineNumber": 26 + }, + { + "text": " {", + "lineNumber": 27 + }, + { + "text": " get => _selectedWorker;", + "lineNumber": 28 + }, + { + "text": " set", + "lineNumber": 29 + }, + { + "text": " {", + "lineNumber": 30 + }, + { + "text": " if (SetAndRaise(ref _selectedWorker, value))", + "lineNumber": 31 + }, + { + "text": " {", + "lineNumber": 32 + }, + { + "text": " UpdateStatusText();", + "lineNumber": 33 + }, + { + "text": " }", + "lineNumber": 34 + }, + { + "text": " }", + "lineNumber": 35 + }, + { + "text": " }", + "lineNumber": 36 + }, + { + "lineNumber": 37 + }, + { + "text": " public string StatusText", + "lineNumber": 38 + }, + { + "text": " {", + "lineNumber": 39 + }, + { + "text": " get => _statusText;", + "lineNumber": 40 + }, + { + "text": " set => SetAndRaise(ref _statusText, value);", + "lineNumber": 41 + }, + { + "text": " }", + "lineNumber": 42 + }, + { + "lineNumber": 43 + }, + { + "text": " public string SelectedWorkerType", + "lineNumber": 44 + }, + { + "text": " {", + "lineNumber": 45 + }, + { + "text": " get => _selectedWorkerType;", + "lineNumber": 46 + }, + { + "text": " set", + "lineNumber": 47 + }, + { + "text": " {", + "lineNumber": 48 + }, + { + "text": " if (SetAndRaise(ref _selectedWorkerType, value))", + "lineNumber": 49 + }, + { + "text": " {", + "lineNumber": 50 + }, + { + "text": " LoadWorkers();", + "lineNumber": 51 + }, + { + "text": " }", + "lineNumber": 52 + }, + { + "text": " }", + "lineNumber": 53 + }, + { + "text": " }", + "lineNumber": 54 + }, + { + "lineNumber": 55 + }, + { + "text": " public string OperationMode", + "lineNumber": 56 + } + ] + }, + "score": 0.2511206865310669 + }, + { + "codeBlock": { + "relativeWorkspacePath": ".\\Views\\WorkerEditWindow.axaml.cs", + "range": { + "startPosition": { + "line": 102 + }, + "endPosition": { + "line": 117 + } + }, + "contents": " {\n if (this.FindControl<ListBox>(\"NetworkPathsListBox\")?.SelectedItem is string path)\n {\n _viewModel.NetworkPaths.Remove(path);\n }\n }\n\n public async Task<bool> ShowDialogAsync(Window parent)\n {\n await base.ShowDialog(parent);\n return _result;\n }\n }\n}", + "signatures": {}, + "detailedLines": [ + { + "text": " {", + "lineNumber": 103 + }, + { + "text": " if (this.FindControl<ListBox>(\"NetworkPathsListBox\")?.SelectedItem is string path)", + "lineNumber": 104 + }, + { + "text": " {", + "lineNumber": 105 + }, + { + "text": " _viewModel.NetworkPaths.Remove(path);", + "lineNumber": 106 + }, + { + "text": " }", + "lineNumber": 107 + }, + { + "text": " }", + "lineNumber": 108 + }, + { + "lineNumber": 109 + }, + { + "text": " public async Task<bool> ShowDialogAsync(Window parent)", + "lineNumber": 110 + }, + { + "text": " {", + "lineNumber": 111 + }, + { + "text": " await base.ShowDialog(parent);", + "lineNumber": 112 + }, + { + "text": " return _result;", + "lineNumber": 113 + }, + { + "text": " }", + "lineNumber": 114 + }, + { + "text": " }", + "lineNumber": 115 + }, + { + "text": "}", + "lineNumber": 116 + } + ] + }, + "score": 0.24458350241184235 + }, + { + "codeBlock": { + "relativeWorkspacePath": ".\\Views\\GlobalSettingsWindow.axaml", + "range": { + "startPosition": { + "line": 31 + }, + "endPosition": { + "line": 55 + } + }, + "contents": " <TabItem Header=\"Flamenco\">\n <StackPanel Margin=\"10\" Spacing=\"10\">\n <TextBlock Text=\"Worker Path:\"/>\n <Grid ColumnDefinitions=\"*,Auto\">\n <TextBox Name=\"FlamencoWorkerPathTextBox\" \n Grid.Column=\"0\" \n Text=\"{Binding FlamencoWorkerPath}\" \n Margin=\"0,0,5,0\"/>\n <Button Name=\"BrowseFlamencoPathButton\" \n Grid.Column=\"1\" \n Content=\"Browse...\" \n Width=\"80\"/>\n </Grid>\n </StackPanel>\n </TabItem>\n </TabControl>\n\n <!-- Buttons -->\n <StackPanel Orientation=\"Horizontal\" HorizontalAlignment=\"Right\" Grid.Row=\"2\" Spacing=\"10\" Margin=\"0,10,0,0\">\n <Button Name=\"OkButton\" Content=\"OK\" Width=\"80\" IsDefault=\"True\"/>\n <Button Name=\"CancelButton\" Content=\"Cancel\" Width=\"80\" IsCancel=\"True\"/>\n </StackPanel>\n </Grid>\n</Window>", + "signatures": {}, + "detailedLines": [ + { + "text": " <TabItem Header=\"Flamenco\">", + "lineNumber": 32 + }, + { + "text": " <StackPanel Margin=\"10\" Spacing=\"10\">", + "lineNumber": 33 + }, + { + "text": " <TextBlock Text=\"Worker Path:\"/>", + "lineNumber": 34 + }, + { + "text": " <Grid ColumnDefinitions=\"*,Auto\">", + "lineNumber": 35 + }, + { + "text": " <TextBox Name=\"FlamencoWorkerPathTextBox\" ", + "lineNumber": 36 + }, + { + "text": " Grid.Column=\"0\" ", + "lineNumber": 37 + }, + { + "text": " Text=\"{Binding FlamencoWorkerPath}\" ", + "lineNumber": 38 + }, + { + "text": " Margin=\"0,0,5,0\"/>", + "lineNumber": 39 + }, + { + "text": " <Button Name=\"BrowseFlamencoPathButton\" ", + "lineNumber": 40 + }, + { + "text": " Grid.Column=\"1\" ", + "lineNumber": 41 + }, + { + "text": " Content=\"Browse...\" ", + "lineNumber": 42 + }, + { + "text": " Width=\"80\"/>", + "lineNumber": 43 + }, + { + "text": " </Grid>", + "lineNumber": 44 + }, + { + "text": " </StackPanel>", + "lineNumber": 45 + }, + { + "text": " </TabItem>", + "lineNumber": 46 + }, + { + "text": " </TabControl>", + "lineNumber": 47 + }, + { + "lineNumber": 48 + }, + { + "text": " <!-- Buttons -->", + "lineNumber": 49 + }, + { + "text": " <StackPanel Orientation=\"Horizontal\" HorizontalAlignment=\"Right\" Grid.Row=\"2\" Spacing=\"10\" Margin=\"0,10,0,0\">", + "lineNumber": 50 + }, + { + "text": " <Button Name=\"OkButton\" Content=\"OK\" Width=\"80\" IsDefault=\"True\"/>", + "lineNumber": 51 + }, + { + "text": " <Button Name=\"CancelButton\" Content=\"Cancel\" Width=\"80\" IsCancel=\"True\"/>", + "lineNumber": 52 + }, + { + "text": " </StackPanel>", + "lineNumber": 53 + }, + { + "text": " </Grid>", + "lineNumber": 54 + }, + { + "text": "</Window>", + "lineNumber": 55 + } + ] + }, + "score": 0.22779864072799683 + }, + { + "codeBlock": { + "relativeWorkspacePath": ".\\Views\\MainWindow.axaml.cs", + "range": { + "startPosition": { + "line": 169 + }, + "endPosition": { + "line": 211 + } + }, + "contents": " await successBox.ShowAsync();\n }\n catch (System.Exception ex)\n {\n var errorBox = MessageBoxManager.GetMessageBoxStandard(\"Error\", \n $\"Failed to stop worker: {ex.Message}\", \n ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Error);\n await errorBox.ShowAsync();\n }\n }\n }\n\n private async void AttachWorkerButton_Click(object? sender, RoutedEventArgs e)\n {\n if (this.FindControl<DataGrid>(\"WorkersGrid\")?.SelectedItem is WorkerConfig worker)\n {\n try\n {\n var vm = (MainWindowViewModel)DataContext!;\n string workerType = vm.OperationMode;\n\n // Verify the worker supports the selected operation mode\n if (workerType == \"sheepit\" && worker.WorkerTypes.SheepIt == null)\n {\n var box = MessageBoxManager.GetMessageBoxStandard(\"Error\", \n $\"Worker '{worker.Name}' does not have SheepIt configured.\", \n ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Error);\n await box.ShowAsync();\n return;\n }\n if (workerType == \"flamenco\" && worker.WorkerTypes.Flamenco == null)\n {\n var box = MessageBoxManager.GetMessageBoxStandard(\"Error\", \n $\"Worker '{worker.Name}' does not have Flamenco configured.\", \n ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Error);\n await box.ShowAsync();\n return;\n }\n\n await _attachService.AttachToWorkerAsync(worker, workerType);\n }\n catch (System.Exception ex)", + "signatures": {}, + "detailedLines": [ + { + "text": " await successBox.ShowAsync();", + "lineNumber": 170 + }, + { + "text": " }", + "lineNumber": 171 + }, + { + "text": " catch (System.Exception ex)", + "lineNumber": 172 + }, + { + "text": " {", + "lineNumber": 173 + }, + { + "text": " var errorBox = MessageBoxManager.GetMessageBoxStandard(\"Error\", ", + "lineNumber": 174 + }, + { + "text": " $\"Failed to stop worker: {ex.Message}\", ", + "lineNumber": 175 + }, + { + "text": " ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Error);", + "lineNumber": 176 + }, + { + "text": " await errorBox.ShowAsync();", + "lineNumber": 177 + }, + { + "text": " }", + "lineNumber": 178 + }, + { + "text": " }", + "lineNumber": 179 + }, + { + "text": " }", + "lineNumber": 180 + }, + { + "lineNumber": 181 + }, + { + "text": " private async void AttachWorkerButton_Click(object? sender, RoutedEventArgs e)", + "lineNumber": 182 + }, + { + "text": " {", + "lineNumber": 183 + }, + { + "text": " if (this.FindControl<DataGrid>(\"WorkersGrid\")?.SelectedItem is WorkerConfig worker)", + "lineNumber": 184 + }, + { + "text": " {", + "lineNumber": 185 + }, + { + "text": " try", + "lineNumber": 186 + }, + { + "text": " {", + "lineNumber": 187 + }, + { + "text": " var vm = (MainWindowViewModel)DataContext!;", + "lineNumber": 188 + }, + { + "text": " string workerType = vm.OperationMode;", + "lineNumber": 189 + }, + { + "lineNumber": 190 + }, + { + "text": " // Verify the worker supports the selected operation mode", + "lineNumber": 191 + }, + { + "text": " if (workerType == \"sheepit\" && worker.WorkerTypes.SheepIt == null)", + "lineNumber": 192 + }, + { + "text": " {", + "lineNumber": 193 + }, + { + "text": " var box = MessageBoxManager.GetMessageBoxStandard(\"Error\", ", + "lineNumber": 194 + }, + { + "text": " $\"Worker '{worker.Name}' does not have SheepIt configured.\", ", + "lineNumber": 195 + }, + { + "text": " ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Error);", + "lineNumber": 196 + }, + { + "text": " await box.ShowAsync();", + "lineNumber": 197 + }, + { + "text": " return;", + "lineNumber": 198 + }, + { + "text": " }", + "lineNumber": 199 + }, + { + "text": " if (workerType == \"flamenco\" && worker.WorkerTypes.Flamenco == null)", + "lineNumber": 200 + }, + { + "text": " {", + "lineNumber": 201 + }, + { + "text": " var box = MessageBoxManager.GetMessageBoxStandard(\"Error\", ", + "lineNumber": 202 + }, + { + "text": " $\"Worker '{worker.Name}' does not have Flamenco configured.\", ", + "lineNumber": 203 + }, + { + "text": " ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Error);", + "lineNumber": 204 + }, + { + "text": " await box.ShowAsync();", + "lineNumber": 205 + }, + { + "text": " return;", + "lineNumber": 206 + }, + { + "text": " }", + "lineNumber": 207 + }, + { + "lineNumber": 208 + }, + { + "text": " await _attachService.AttachToWorkerAsync(worker, workerType);", + "lineNumber": 209 + }, + { + "text": " }", + "lineNumber": 210 + }, + { + "text": " catch (System.Exception ex)", + "lineNumber": 211 + } + ] + }, + "score": 0.21573659777641296 + }, + { + "codeBlock": { + "relativeWorkspacePath": ".\\Views\\GlobalSettingsWindow.axaml.cs", + "range": { + "startPosition": { + "line": 52 + }, + "endPosition": { + "line": 96 + } + }, + "contents": " {\n _result = false;\n Close();\n }\n\n private void ToggleRenderKeyButton_Click(object? sender, RoutedEventArgs e)\n {\n var textBox = this.FindControl<Avalonia.Controls.TextBox>(\"SheepItRenderKeyTextBox\");\n if (textBox != null)\n {\n _viewModel.IsRenderKeyVisible = !_viewModel.IsRenderKeyVisible;\n textBox.PasswordChar = _viewModel.IsRenderKeyVisible ? '\\0' : '*';\n var button = sender as Button;\n if (button != null)\n {\n button.Content = _viewModel.IsRenderKeyVisible ? \"🙈\" : \"👁\";\n }\n }\n }\n\n private async void BrowseFlamencoPathButton_Click(object? sender, RoutedEventArgs e)\n {\n var topLevel = TopLevel.GetTopLevel(this);\n if (topLevel?.StorageProvider.CanPickFolder == true)\n {\n var folders = await topLevel.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions\n {\n Title = \"Select Flamenco Worker Path\"\n });\n \n if (folders.Count > 0 && folders[0].TryGetLocalPath() is { } localPath)\n {\n _viewModel.FlamencoWorkerPath = localPath;\n }\n }\n }\n\n public async Task<bool> ShowDialogAsync(Window parent)\n {\n await base.ShowDialog(parent);\n return _result;\n }\n }\n}", + "signatures": {}, + "detailedLines": [ + { + "text": " {", + "lineNumber": 53 + }, + { + "text": " _result = false;", + "lineNumber": 54 + }, + { + "text": " Close();", + "lineNumber": 55 + }, + { + "text": " }", + "lineNumber": 56 + }, + { + "lineNumber": 57 + }, + { + "text": " private void ToggleRenderKeyButton_Click(object? sender, RoutedEventArgs e)", + "lineNumber": 58 + }, + { + "text": " {", + "lineNumber": 59 + }, + { + "text": " var textBox = this.FindControl<Avalonia.Controls.TextBox>(\"SheepItRenderKeyTextBox\");", + "lineNumber": 60 + }, + { + "text": " if (textBox != null)", + "lineNumber": 61 + }, + { + "text": " {", + "lineNumber": 62 + }, + { + "text": " _viewModel.IsRenderKeyVisible = !_viewModel.IsRenderKeyVisible;", + "lineNumber": 63 + }, + { + "text": " textBox.PasswordChar = _viewModel.IsRenderKeyVisible ? '\\0' : '*';", + "lineNumber": 64 + }, + { + "text": " var button = sender as Button;", + "lineNumber": 65 + }, + { + "text": " if (button != null)", + "lineNumber": 66 + }, + { + "text": " {", + "lineNumber": 67 + }, + { + "text": " button.Content = _viewModel.IsRenderKeyVisible ? \"🙈\" : \"👁\";", + "lineNumber": 68 + }, + { + "text": " }", + "lineNumber": 69 + }, + { + "text": " }", + "lineNumber": 70 + }, + { + "text": " }", + "lineNumber": 71 + }, + { + "lineNumber": 72 + }, + { + "text": " private async void BrowseFlamencoPathButton_Click(object? sender, RoutedEventArgs e)", + "lineNumber": 73 + }, + { + "text": " {", + "lineNumber": 74 + }, + { + "text": " var topLevel = TopLevel.GetTopLevel(this);", + "lineNumber": 75 + }, + { + "text": " if (topLevel?.StorageProvider.CanPickFolder == true)", + "lineNumber": 76 + }, + { + "text": " {", + "lineNumber": 77 + }, + { + "text": " var folders = await topLevel.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions", + "lineNumber": 78 + }, + { + "text": " {", + "lineNumber": 79 + }, + { + "text": " Title = \"Select Flamenco Worker Path\"", + "lineNumber": 80 + }, + { + "text": " });", + "lineNumber": 81 + }, + { + "text": " ", + "lineNumber": 82 + }, + { + "text": " if (folders.Count > 0 && folders[0].TryGetLocalPath() is { } localPath)", + "lineNumber": 83 + }, + { + "text": " {", + "lineNumber": 84 + }, + { + "text": " _viewModel.FlamencoWorkerPath = localPath;", + "lineNumber": 85 + }, + { + "text": " }", + "lineNumber": 86 + }, + { + "text": " }", + "lineNumber": 87 + }, + { + "text": " }", + "lineNumber": 88 + }, + { + "lineNumber": 89 + }, + { + "text": " public async Task<bool> ShowDialogAsync(Window parent)", + "lineNumber": 90 + }, + { + "text": " {", + "lineNumber": 91 + }, + { + "text": " await base.ShowDialog(parent);", + "lineNumber": 92 + }, + { + "text": " return _result;", + "lineNumber": 93 + }, + { + "text": " }", + "lineNumber": 94 + }, + { + "text": " }", + "lineNumber": 95 + }, + { + "text": "}", + "lineNumber": 96 + } + ] + }, + "score": 0.21289044618606567 + }, + { + "codeBlock": { + "relativeWorkspacePath": ".\\Views\\GlobalSettingsWindow.axaml.cs", + "range": { + "startPosition": {}, + "endPosition": { + "line": 58 + } + }, + "contents": "using System.Threading.Tasks;\nusing Avalonia.Controls;\nusing Avalonia.Interactivity;\nusing Avalonia.Platform.Storage;\nusing UnifiedFarmLauncher.Services;\nusing UnifiedFarmLauncher.ViewModels;\n\nnamespace UnifiedFarmLauncher.Views\n{\n public partial class GlobalSettingsWindow : Window\n {\n private readonly GlobalSettingsViewModel _viewModel;\n private bool _result;\n\n public GlobalSettingsWindow()\n {\n InitializeComponent();\n var configService = new ConfigService();\n _viewModel = new GlobalSettingsViewModel(configService);\n DataContext = _viewModel;\n SetupEventHandlers();\n }\n\n private void InitializeComponent()\n {\n Avalonia.Markup.Xaml.AvaloniaXamlLoader.Load(this);\n }\n\n private void SetupEventHandlers()\n {\n this.FindControl<Button>(\"OkButton\")!.Click += OkButton_Click;\n this.FindControl<Button>(\"CancelButton\")!.Click += CancelButton_Click;\n this.FindControl<Button>(\"ToggleRenderKeyButton\")!.Click += ToggleRenderKeyButton_Click;\n this.FindControl<Button>(\"BrowseFlamencoPathButton\")!.Click += BrowseFlamencoPathButton_Click;\n }\n\n private void OkButton_Click(object? sender, RoutedEventArgs e)\n {\n try\n {\n _viewModel.Save();\n _result = true;\n Close();\n }\n catch (System.Exception ex)\n {\n // Could show error message here\n System.Diagnostics.Debug.WriteLine($\"Failed to save global settings: {ex.Message}\");\n }\n }\n\n private void CancelButton_Click(object? sender, RoutedEventArgs e)\n {\n _result = false;\n Close();\n }\n\n private void ToggleRenderKeyButton_Click(object? sender, RoutedEventArgs e)", + "signatures": {}, + "detailedLines": [ + { + "text": "using System.Threading.Tasks;", + "lineNumber": 1 + }, + { + "text": "using Avalonia.Controls;", + "lineNumber": 2 + }, + { + "text": "using Avalonia.Interactivity;", + "lineNumber": 3 + }, + { + "text": "using Avalonia.Platform.Storage;", + "lineNumber": 4 + }, + { + "text": "using UnifiedFarmLauncher.Services;", + "lineNumber": 5 + }, + { + "text": "using UnifiedFarmLauncher.ViewModels;", + "lineNumber": 6 + }, + { + "lineNumber": 7 + }, + { + "text": "namespace UnifiedFarmLauncher.Views", + "lineNumber": 8 + }, + { + "text": "{", + "lineNumber": 9 + }, + { + "text": " public partial class GlobalSettingsWindow : Window", + "lineNumber": 10 + }, + { + "text": " {", + "lineNumber": 11 + }, + { + "text": " private readonly GlobalSettingsViewModel _viewModel;", + "lineNumber": 12 + }, + { + "text": " private bool _result;", + "lineNumber": 13 + }, + { + "lineNumber": 14 + }, + { + "text": " public GlobalSettingsWindow()", + "lineNumber": 15 + }, + { + "text": " {", + "lineNumber": 16 + }, + { + "text": " InitializeComponent();", + "lineNumber": 17 + }, + { + "text": " var configService = new ConfigService();", + "lineNumber": 18 + }, + { + "text": " _viewModel = new GlobalSettingsViewModel(configService);", + "lineNumber": 19 + }, + { + "text": " DataContext = _viewModel;", + "lineNumber": 20 + }, + { + "text": " SetupEventHandlers();", + "lineNumber": 21 + }, + { + "text": " }", + "lineNumber": 22 + }, + { + "lineNumber": 23 + }, + { + "text": " private void InitializeComponent()", + "lineNumber": 24 + }, + { + "text": " {", + "lineNumber": 25 + }, + { + "text": " Avalonia.Markup.Xaml.AvaloniaXamlLoader.Load(this);", + "lineNumber": 26 + }, + { + "text": " }", + "lineNumber": 27 + }, + { + "lineNumber": 28 + }, + { + "text": " private void SetupEventHandlers()", + "lineNumber": 29 + }, + { + "text": " {", + "lineNumber": 30 + }, + { + "text": " this.FindControl<Button>(\"OkButton\")!.Click += OkButton_Click;", + "lineNumber": 31 + }, + { + "text": " this.FindControl<Button>(\"CancelButton\")!.Click += CancelButton_Click;", + "lineNumber": 32 + }, + { + "text": " this.FindControl<Button>(\"ToggleRenderKeyButton\")!.Click += ToggleRenderKeyButton_Click;", + "lineNumber": 33 + }, + { + "text": " this.FindControl<Button>(\"BrowseFlamencoPathButton\")!.Click += BrowseFlamencoPathButton_Click;", + "lineNumber": 34 + }, + { + "text": " }", + "lineNumber": 35 + }, + { + "lineNumber": 36 + }, + { + "text": " private void OkButton_Click(object? sender, RoutedEventArgs e)", + "lineNumber": 37 + }, + { + "text": " {", + "lineNumber": 38 + }, + { + "text": " try", + "lineNumber": 39 + }, + { + "text": " {", + "lineNumber": 40 + }, + { + "text": " _viewModel.Save();", + "lineNumber": 41 + }, + { + "text": " _result = true;", + "lineNumber": 42 + }, + { + "text": " Close();", + "lineNumber": 43 + }, + { + "text": " }", + "lineNumber": 44 + }, + { + "text": " catch (System.Exception ex)", + "lineNumber": 45 + }, + { + "text": " {", + "lineNumber": 46 + }, + { + "text": " // Could show error message here", + "lineNumber": 47 + }, + { + "text": " System.Diagnostics.Debug.WriteLine($\"Failed to save global settings: {ex.Message}\");", + "lineNumber": 48 + }, + { + "text": " }", + "lineNumber": 49 + }, + { + "text": " }", + "lineNumber": 50 + }, + { + "lineNumber": 51 + }, + { + "text": " private void CancelButton_Click(object? sender, RoutedEventArgs e)", + "lineNumber": 52 + }, + { + "text": " {", + "lineNumber": 53 + }, + { + "text": " _result = false;", + "lineNumber": 54 + }, + { + "text": " Close();", + "lineNumber": 55 + }, + { + "text": " }", + "lineNumber": 56 + }, + { + "lineNumber": 57 + }, + { + "text": " private void ToggleRenderKeyButton_Click(object? sender, RoutedEventArgs e)", + "lineNumber": 58 + } + ] + }, + "score": 0.20524029433727264 + }, + { + "codeBlock": { + "relativeWorkspacePath": ".\\Views\\MainWindow.axaml.cs", + "range": { + "startPosition": { + "line": 136 + }, + "endPosition": { + "line": 172 + } + }, + "contents": " }\n\n private async void StopWorkerButton_Click(object? sender, RoutedEventArgs e)\n {\n if (this.FindControl<DataGrid>(\"WorkersGrid\")?.SelectedItem is WorkerConfig worker)\n {\n try\n {\n var vm = (MainWindowViewModel)DataContext!;\n string workerType = vm.OperationMode;\n\n // Verify the worker supports the selected operation mode\n if (workerType == \"sheepit\" && worker.WorkerTypes.SheepIt == null)\n {\n var box = MessageBoxManager.GetMessageBoxStandard(\"Error\", \n $\"Worker '{worker.Name}' does not have SheepIt configured.\", \n ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Error);\n await box.ShowAsync();\n return;\n }\n if (workerType == \"flamenco\" && worker.WorkerTypes.Flamenco == null)\n {\n var box = MessageBoxManager.GetMessageBoxStandard(\"Error\", \n $\"Worker '{worker.Name}' does not have Flamenco configured.\", \n ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Error);\n await box.ShowAsync();\n return;\n }\n\n await _controllerService.StopWorkerAsync(worker, workerType);\n var successBox = MessageBoxManager.GetMessageBoxStandard(\"Stop Worker\", \n $\"Stop command sent to worker '{worker.Name}' ({vm.OperationModeDisplayName}).\", \n ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Info);\n await successBox.ShowAsync();\n }\n catch (System.Exception ex)", + "signatures": {}, + "detailedLines": [ + { + "text": " }", + "lineNumber": 137 + }, + { + "lineNumber": 138 + }, + { + "text": " private async void StopWorkerButton_Click(object? sender, RoutedEventArgs e)", + "lineNumber": 139 + }, + { + "text": " {", + "lineNumber": 140 + }, + { + "text": " if (this.FindControl<DataGrid>(\"WorkersGrid\")?.SelectedItem is WorkerConfig worker)", + "lineNumber": 141 + }, + { + "text": " {", + "lineNumber": 142 + }, + { + "text": " try", + "lineNumber": 143 + }, + { + "text": " {", + "lineNumber": 144 + }, + { + "text": " var vm = (MainWindowViewModel)DataContext!;", + "lineNumber": 145 + }, + { + "text": " string workerType = vm.OperationMode;", + "lineNumber": 146 + }, + { + "lineNumber": 147 + }, + { + "text": " // Verify the worker supports the selected operation mode", + "lineNumber": 148 + }, + { + "text": " if (workerType == \"sheepit\" && worker.WorkerTypes.SheepIt == null)", + "lineNumber": 149 + }, + { + "text": " {", + "lineNumber": 150 + }, + { + "text": " var box = MessageBoxManager.GetMessageBoxStandard(\"Error\", ", + "lineNumber": 151 + }, + { + "text": " $\"Worker '{worker.Name}' does not have SheepIt configured.\", ", + "lineNumber": 152 + }, + { + "text": " ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Error);", + "lineNumber": 153 + }, + { + "text": " await box.ShowAsync();", + "lineNumber": 154 + }, + { + "text": " return;", + "lineNumber": 155 + }, + { + "text": " }", + "lineNumber": 156 + }, + { + "text": " if (workerType == \"flamenco\" && worker.WorkerTypes.Flamenco == null)", + "lineNumber": 157 + }, + { + "text": " {", + "lineNumber": 158 + }, + { + "text": " var box = MessageBoxManager.GetMessageBoxStandard(\"Error\", ", + "lineNumber": 159 + }, + { + "text": " $\"Worker '{worker.Name}' does not have Flamenco configured.\", ", + "lineNumber": 160 + }, + { + "text": " ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Error);", + "lineNumber": 161 + }, + { + "text": " await box.ShowAsync();", + "lineNumber": 162 + }, + { + "text": " return;", + "lineNumber": 163 + }, + { + "text": " }", + "lineNumber": 164 + }, + { + "lineNumber": 165 + }, + { + "text": " await _controllerService.StopWorkerAsync(worker, workerType);", + "lineNumber": 166 + }, + { + "text": " var successBox = MessageBoxManager.GetMessageBoxStandard(\"Stop Worker\", ", + "lineNumber": 167 + }, + { + "text": " $\"Stop command sent to worker '{worker.Name}' ({vm.OperationModeDisplayName}).\", ", + "lineNumber": 168 + }, + { + "text": " ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Info);", + "lineNumber": 169 + }, + { + "text": " await successBox.ShowAsync();", + "lineNumber": 170 + }, + { + "text": " }", + "lineNumber": 171 + }, + { + "text": " catch (System.Exception ex)", + "lineNumber": 172 + } + ] + }, + "score": 0.19811619818210602 + }, + { + "codeBlock": { + "relativeWorkspacePath": ".\\Views\\MainWindow.axaml", + "range": { + "startPosition": {}, + "endPosition": { + "line": 36 + } + }, + "contents": "<Window xmlns=\"https://github.com/avaloniaui\"\n xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n xmlns:vm=\"using:UnifiedFarmLauncher.ViewModels\"\n xmlns:models=\"using:UnifiedFarmLauncher.Models\"\n x:Class=\"UnifiedFarmLauncher.Views.MainWindow\"\n x:DataType=\"vm:MainWindowViewModel\"\n Title=\"Unified Farm Launcher\"\n Width=\"1000\" Height=\"700\"\n MinWidth=\"800\" MinHeight=\"600\">\n <Grid RowDefinitions=\"Auto,Auto,*,Auto\">\n <!-- Toolbar -->\n <Grid Grid.Row=\"0\" Margin=\"5\">\n <Grid.ColumnDefinitions>\n <ColumnDefinition Width=\"*\"/>\n <ColumnDefinition Width=\"Auto\"/>\n </Grid.ColumnDefinitions>\n <StackPanel Orientation=\"Horizontal\" Grid.Column=\"0\">\n <Button Name=\"AddWorkerButton\" Content=\"Add Worker\" Margin=\"5\" Width=\"120\"/>\n <Button Name=\"EditWorkerButton\" Content=\"Edit Worker\" Margin=\"5\" Width=\"120\"/>\n <Button Name=\"DeleteWorkerButton\" Content=\"Delete Worker\" Margin=\"5\" Width=\"120\"/>\n <Separator Margin=\"10,0\"/>\n <Button Name=\"StartWorkerButton\" Content=\"Start\" Margin=\"5\" Width=\"80\"/>\n <Button Name=\"StopWorkerButton\" Content=\"Stop\" Margin=\"5\" Width=\"80\"/>\n <Button Name=\"AttachWorkerButton\" Content=\"Attach\" Margin=\"5\" Width=\"80\"/>\n <Separator Margin=\"10,0\"/>\n <Button Name=\"SettingsButton\" Content=\"Settings\" Margin=\"5\" Width=\"80\"/>\n </StackPanel>\n <!-- Operation Mode Toggle Button -->\n <Button Name=\"OperationModeToggleButton\" Grid.Column=\"1\" \n HorizontalAlignment=\"Right\" \n VerticalAlignment=\"Center\"\n Margin=\"5\"\n Padding=\"10,5\"\n MinWidth=\"120\">\n <StackPanel Orientation=\"Horizontal\" Spacing=\"5\">\n <TextBlock Text=\"{Binding OperationModeIcon}\" FontSize=\"16\" VerticalAlignment=\"Center\"/>", + "signatures": {}, + "detailedLines": [ + { + "text": "<Window xmlns=\"https://github.com/avaloniaui\"", + "lineNumber": 1 + }, + { + "text": " xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"", + "lineNumber": 2 + }, + { + "text": " xmlns:vm=\"using:UnifiedFarmLauncher.ViewModels\"", + "lineNumber": 3 + }, + { + "text": " xmlns:models=\"using:UnifiedFarmLauncher.Models\"", + "lineNumber": 4 + }, + { + "text": " x:Class=\"UnifiedFarmLauncher.Views.MainWindow\"", + "lineNumber": 5 + }, + { + "text": " x:DataType=\"vm:MainWindowViewModel\"", + "lineNumber": 6 + }, + { + "text": " Title=\"Unified Farm Launcher\"", + "lineNumber": 7 + }, + { + "text": " Width=\"1000\" Height=\"700\"", + "lineNumber": 8 + }, + { + "text": " MinWidth=\"800\" MinHeight=\"600\">", + "lineNumber": 9 + }, + { + "text": " <Grid RowDefinitions=\"Auto,Auto,*,Auto\">", + "lineNumber": 10 + }, + { + "text": " <!-- Toolbar -->", + "lineNumber": 11 + }, + { + "text": " <Grid Grid.Row=\"0\" Margin=\"5\">", + "lineNumber": 12 + }, + { + "text": " <Grid.ColumnDefinitions>", + "lineNumber": 13 + }, + { + "text": " <ColumnDefinition Width=\"*\"/>", + "lineNumber": 14 + }, + { + "text": " <ColumnDefinition Width=\"Auto\"/>", + "lineNumber": 15 + }, + { + "text": " </Grid.ColumnDefinitions>", + "lineNumber": 16 + }, + { + "text": " <StackPanel Orientation=\"Horizontal\" Grid.Column=\"0\">", + "lineNumber": 17 + }, + { + "text": " <Button Name=\"AddWorkerButton\" Content=\"Add Worker\" Margin=\"5\" Width=\"120\"/>", + "lineNumber": 18 + }, + { + "text": " <Button Name=\"EditWorkerButton\" Content=\"Edit Worker\" Margin=\"5\" Width=\"120\"/>", + "lineNumber": 19 + }, + { + "text": " <Button Name=\"DeleteWorkerButton\" Content=\"Delete Worker\" Margin=\"5\" Width=\"120\"/>", + "lineNumber": 20 + }, + { + "text": " <Separator Margin=\"10,0\"/>", + "lineNumber": 21 + }, + { + "text": " <Button Name=\"StartWorkerButton\" Content=\"Start\" Margin=\"5\" Width=\"80\"/>", + "lineNumber": 22 + }, + { + "text": " <Button Name=\"StopWorkerButton\" Content=\"Stop\" Margin=\"5\" Width=\"80\"/>", + "lineNumber": 23 + }, + { + "text": " <Button Name=\"AttachWorkerButton\" Content=\"Attach\" Margin=\"5\" Width=\"80\"/>", + "lineNumber": 24 + }, + { + "text": " <Separator Margin=\"10,0\"/>", + "lineNumber": 25 + }, + { + "text": " <Button Name=\"SettingsButton\" Content=\"Settings\" Margin=\"5\" Width=\"80\"/>", + "lineNumber": 26 + }, + { + "text": " </StackPanel>", + "lineNumber": 27 + }, + { + "text": " <!-- Operation Mode Toggle Button -->", + "lineNumber": 28 + }, + { + "text": " <Button Name=\"OperationModeToggleButton\" Grid.Column=\"1\" ", + "lineNumber": 29 + }, + { + "text": " HorizontalAlignment=\"Right\" ", + "lineNumber": 30 + }, + { + "text": " VerticalAlignment=\"Center\"", + "lineNumber": 31 + }, + { + "text": " Margin=\"5\"", + "lineNumber": 32 + }, + { + "text": " Padding=\"10,5\"", + "lineNumber": 33 + }, + { + "text": " MinWidth=\"120\">", + "lineNumber": 34 + }, + { + "text": " <StackPanel Orientation=\"Horizontal\" Spacing=\"5\">", + "lineNumber": 35 + }, + { + "text": " <TextBlock Text=\"{Binding OperationModeIcon}\" FontSize=\"16\" VerticalAlignment=\"Center\"/>", + "lineNumber": 36 + } + ] + }, + "score": 0.1752990484237671 + }, + { + "codeBlock": { + "relativeWorkspacePath": ".\\Views\\MainWindow.axaml.cs", + "range": { + "startPosition": {}, + "endPosition": { + "line": 34 + } + }, + "contents": "using System.Linq;\nusing Avalonia.Controls;\nusing Avalonia.Interactivity;\nusing UnifiedFarmLauncher.Models;\nusing UnifiedFarmLauncher.Services;\nusing UnifiedFarmLauncher.ViewModels;\nusing Avalonia.Controls.Primitives;\nusing MsBox.Avalonia;\nusing MsBox.Avalonia.Enums;\n\nnamespace UnifiedFarmLauncher.Views\n{\n public partial class MainWindow : Window\n {\n private readonly ConfigService _configService = new();\n private readonly SshService _sshService = new();\n private readonly WorkerControllerService _controllerService;\n private readonly AttachService _attachService;\n\n public MainWindow()\n {\n InitializeComponent();\n _controllerService = new WorkerControllerService(_sshService, _configService);\n _attachService = new AttachService(_sshService, _controllerService);\n DataContext = new MainWindowViewModel();\n SetupEventHandlers();\n }\n\n private void InitializeComponent()\n {\n Avalonia.Markup.Xaml.AvaloniaXamlLoader.Load(this);\n }\n\n private void SetupEventHandlers()", + "signatures": {}, + "detailedLines": [ + { + "text": "using System.Linq;", + "lineNumber": 1 + }, + { + "text": "using Avalonia.Controls;", + "lineNumber": 2 + }, + { + "text": "using Avalonia.Interactivity;", + "lineNumber": 3 + }, + { + "text": "using UnifiedFarmLauncher.Models;", + "lineNumber": 4 + }, + { + "text": "using UnifiedFarmLauncher.Services;", + "lineNumber": 5 + }, + { + "text": "using UnifiedFarmLauncher.ViewModels;", + "lineNumber": 6 + }, + { + "text": "using Avalonia.Controls.Primitives;", + "lineNumber": 7 + }, + { + "text": "using MsBox.Avalonia;", + "lineNumber": 8 + }, + { + "text": "using MsBox.Avalonia.Enums;", + "lineNumber": 9 + }, + { + "lineNumber": 10 + }, + { + "text": "namespace UnifiedFarmLauncher.Views", + "lineNumber": 11 + }, + { + "text": "{", + "lineNumber": 12 + }, + { + "text": " public partial class MainWindow : Window", + "lineNumber": 13 + }, + { + "text": " {", + "lineNumber": 14 + }, + { + "text": " private readonly ConfigService _configService = new();", + "lineNumber": 15 + }, + { + "text": " private readonly SshService _sshService = new();", + "lineNumber": 16 + }, + { + "text": " private readonly WorkerControllerService _controllerService;", + "lineNumber": 17 + }, + { + "text": " private readonly AttachService _attachService;", + "lineNumber": 18 + }, + { + "lineNumber": 19 + }, + { + "text": " public MainWindow()", + "lineNumber": 20 + }, + { + "text": " {", + "lineNumber": 21 + }, + { + "text": " InitializeComponent();", + "lineNumber": 22 + }, + { + "text": " _controllerService = new WorkerControllerService(_sshService, _configService);", + "lineNumber": 23 + }, + { + "text": " _attachService = new AttachService(_sshService, _controllerService);", + "lineNumber": 24 + }, + { + "text": " DataContext = new MainWindowViewModel();", + "lineNumber": 25 + }, + { + "text": " SetupEventHandlers();", + "lineNumber": 26 + }, + { + "text": " }", + "lineNumber": 27 + }, + { + "lineNumber": 28 + }, + { + "text": " private void InitializeComponent()", + "lineNumber": 29 + }, + { + "text": " {", + "lineNumber": 30 + }, + { + "text": " Avalonia.Markup.Xaml.AvaloniaXamlLoader.Load(this);", + "lineNumber": 31 + }, + { + "text": " }", + "lineNumber": 32 + }, + { + "lineNumber": 33 + }, + { + "text": " private void SetupEventHandlers()", + "lineNumber": 34 + } + ] + }, + "score": 0.16454540193080902 + }, + { + "codeBlock": { + "relativeWorkspacePath": ".\\Views\\MainWindow.axaml.cs", + "range": { + "startPosition": { + "line": 101 + }, + "endPosition": { + "line": 139 + } + }, + "contents": " string? workerType = vm.OperationMode;\n\n // Verify the worker supports the selected operation mode\n if (workerType == \"sheepit\" && worker.WorkerTypes.SheepIt == null)\n {\n var box = MessageBoxManager.GetMessageBoxStandard(\"Error\", \n $\"Worker '{worker.Name}' does not have SheepIt configured.\", \n ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Error);\n await box.ShowAsync();\n return;\n }\n if (workerType == \"flamenco\" && worker.WorkerTypes.Flamenco == null)\n {\n var box = MessageBoxManager.GetMessageBoxStandard(\"Error\", \n $\"Worker '{worker.Name}' does not have Flamenco configured.\", \n ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Error);\n await box.ShowAsync();\n return;\n }\n\n await _controllerService.StartWorkerAsync(worker, workerType);\n var successBox = MessageBoxManager.GetMessageBoxStandard(\"Start Worker\", \n $\"Worker '{worker.Name}' ({vm.OperationModeDisplayName}) started successfully.\", \n ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Success);\n await successBox.ShowAsync();\n vm.RefreshWorkers();\n }\n catch (System.Exception ex)\n {\n var errorBox = MessageBoxManager.GetMessageBoxStandard(\"Error\", \n $\"Failed to start worker: {ex.Message}\", \n ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Error);\n await errorBox.ShowAsync();\n }\n }\n }\n\n private async void StopWorkerButton_Click(object? sender, RoutedEventArgs e)", + "signatures": {}, + "detailedLines": [ + { + "text": " string? workerType = vm.OperationMode;", + "lineNumber": 102 + }, + { + "lineNumber": 103 + }, + { + "text": " // Verify the worker supports the selected operation mode", + "lineNumber": 104 + }, + { + "text": " if (workerType == \"sheepit\" && worker.WorkerTypes.SheepIt == null)", + "lineNumber": 105 + }, + { + "text": " {", + "lineNumber": 106 + }, + { + "text": " var box = MessageBoxManager.GetMessageBoxStandard(\"Error\", ", + "lineNumber": 107 + }, + { + "text": " $\"Worker '{worker.Name}' does not have SheepIt configured.\", ", + "lineNumber": 108 + }, + { + "text": " ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Error);", + "lineNumber": 109 + }, + { + "text": " await box.ShowAsync();", + "lineNumber": 110 + }, + { + "text": " return;", + "lineNumber": 111 + }, + { + "text": " }", + "lineNumber": 112 + }, + { + "text": " if (workerType == \"flamenco\" && worker.WorkerTypes.Flamenco == null)", + "lineNumber": 113 + }, + { + "text": " {", + "lineNumber": 114 + }, + { + "text": " var box = MessageBoxManager.GetMessageBoxStandard(\"Error\", ", + "lineNumber": 115 + }, + { + "text": " $\"Worker '{worker.Name}' does not have Flamenco configured.\", ", + "lineNumber": 116 + }, + { + "text": " ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Error);", + "lineNumber": 117 + }, + { + "text": " await box.ShowAsync();", + "lineNumber": 118 + }, + { + "text": " return;", + "lineNumber": 119 + }, + { + "text": " }", + "lineNumber": 120 + }, + { + "lineNumber": 121 + }, + { + "text": " await _controllerService.StartWorkerAsync(worker, workerType);", + "lineNumber": 122 + }, + { + "text": " var successBox = MessageBoxManager.GetMessageBoxStandard(\"Start Worker\", ", + "lineNumber": 123 + }, + { + "text": " $\"Worker '{worker.Name}' ({vm.OperationModeDisplayName}) started successfully.\", ", + "lineNumber": 124 + }, + { + "text": " ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Success);", + "lineNumber": 125 + }, + { + "text": " await successBox.ShowAsync();", + "lineNumber": 126 + }, + { + "text": " vm.RefreshWorkers();", + "lineNumber": 127 + }, + { + "text": " }", + "lineNumber": 128 + }, + { + "text": " catch (System.Exception ex)", + "lineNumber": 129 + }, + { + "text": " {", + "lineNumber": 130 + }, + { + "text": " var errorBox = MessageBoxManager.GetMessageBoxStandard(\"Error\", ", + "lineNumber": 131 + }, + { + "text": " $\"Failed to start worker: {ex.Message}\", ", + "lineNumber": 132 + }, + { + "text": " ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Error);", + "lineNumber": 133 + }, + { + "text": " await errorBox.ShowAsync();", + "lineNumber": 134 + }, + { + "text": " }", + "lineNumber": 135 + }, + { + "text": " }", + "lineNumber": 136 + }, + { + "text": " }", + "lineNumber": 137 + }, + { + "lineNumber": 138 + }, + { + "text": " private async void StopWorkerButton_Click(object? sender, RoutedEventArgs e)", + "lineNumber": 139 + } + ] + }, + "score": 0.15338963270187378 + } + ] +} +``` +Status: **completed** + + +
+
+ +--- + + +The ComboBox binding issue: `SelectedItem` is bound to a string (`SheepItGpu`), but the items are `ComboBoxItem` objects, so the match fails. Also, if the saved GPU is empty, nothing gets selected. + +Creating a plan to fix this: + + +--- + + +
+Tool use: **create_plan** + + +Parameters: + +```json +{ + "plan": "# Fix GPU Selection Persistence\n\n## Problem\nThe GPU ComboBox in the worker edit window doesn't properly bind to the `SheepItGpu` property because:\n1. The ComboBox uses `ComboBoxItem` objects with `Content` properties, but `SelectedItem` is bound to a string\n2. When the saved GPU value is empty or doesn't match, the ComboBox doesn't select anything\n3. The binding mismatch prevents proper saving and loading of GPU selection\n\n## Solution\n\n### 1. Fix ComboBox Binding in `Views/WorkerEditWindow.axaml`\nChange the ComboBox to use plain strings instead of `ComboBoxItem` objects. This allows direct binding to the string property.\n\n**Current code (lines 37-43):**\n```xml\n<ComboBox Name=\"GpuComboBox\" IsVisible=\"{Binding HasSheepIt}\" SelectedItem=\"{Binding SheepItGpu}\">\n <ComboBox.Items>\n <ComboBoxItem Content=\"OPTIX_0\"/>\n <ComboBoxItem Content=\"CUDA_0\"/>\n <ComboBoxItem Content=\"OPENCL_0\"/>\n </ComboBox.Items>\n</ComboBox>\n```\n\n**Change to:**\n```xml\n<ComboBox Name=\"GpuComboBox\" IsVisible=\"{Binding HasSheepIt}\" SelectedItem=\"{Binding SheepItGpu}\">\n <ComboBox.Items>\n <x:String>OPTIX_0</x:String>\n <x:String>CUDA_0</x:String>\n <x:String>OPENCL_0</x:String>\n </ComboBox.Items>\n</ComboBox>\n```\n\nOr use an Items collection in the ViewModel for better maintainability.\n\n### 2. Ensure Default GPU Value is Set\nIn `ViewModels/WorkerEditViewModel.cs`, ensure that when loading a worker with an empty GPU value, it defaults to \"OPTIX_0\":\n\n**Update `LoadWorker` method (around line 108):**\n```csharp\nif (worker.WorkerTypes.SheepIt != null)\n{\n HasSheepIt = true;\n SheepItGpu = string.IsNullOrEmpty(worker.WorkerTypes.SheepIt.Gpu) \n ? \"OPTIX_0\" \n : worker.WorkerTypes.SheepIt.Gpu;\n}\n```\n\n### 3. Verify GPU is Used in Start Function\nConfirm that `Services/WorkerControllerService.cs` correctly uses the GPU value from the worker configuration (line 145 already does this correctly - no changes needed).\n\n## Files to Modify\n- `Views/WorkerEditWindow.axaml` - Fix ComboBox items to use strings\n- `ViewModels/WorkerEditViewModel.cs` - Add default GPU value handling when loading\n\n## Testing\nAfter the fix:\n1. Open worker settings and select a GPU (e.g., CUDA_0)\n2. Save the worker\n3. Reopen the worker settings - the GPU selection should persist\n4. Start a worker and verify the correct GPU is used in the SheepIt command line", + "name": "Fix GPU Selection Persistence", + "todos": [ + { + "content": "Fix ComboBox in WorkerEditWindow.axaml to use plain strings instead of ComboBoxItem objects", + "status": "pending", + "id": "1" + }, + { + "content": "Add default GPU value handling in WorkerEditViewModel.LoadWorker when GPU is empty", + "status": "pending", + "id": "2" + }, + { + "content": "Verify the GPU value is correctly saved and loaded in the configuration", + "status": "pending", + "id": "3" + } + ], + "overview": "Fix the GPU ComboBox binding issue in WorkerEditWindow so that GPU selection persists correctly when saving and loading worker configurations." +} +``` +Additional data: + +```json +{ + "reviewData": { + "status": "Requested", + "selectedOption": "none", + "isShowingInput": false + }, + "planUri": "c:\\Users\\Nathan\\.cursor\\plans\\fix_gpu_selection_persistence_9eaace6a.plan.md", + "hasOpenedEditor": true +} +``` +Result: + +```json +{ + "rejected": {} +} +``` +Status: **completed** + + +
+
+ +--- + +_**User**_ + +Implement the plan as specified, it is attached for your reference. Do NOT edit the plan file itself. + +To-do's from the plan have already been created. Do not create them again. Mark them as in_progress as you work, starting with the first one. Don't stop until you have completed all the to-dos. + +--- + +_**Agent (model default, mode Agent)**_ + + +Implementing the plan to fix GPU selection persistence. Starting with the first task. + + +--- + + +
Tool use: **todo_write** • Todo List + +- [-] Fix ComboBox in WorkerEditWindow.axaml to use plain strings instead of ComboBoxItem objects +- [ ] Add default GPU value handling in WorkerEditViewModel.LoadWorker when GPU is empty +- [ ] Verify the GPU value is correctly saved and loaded in the configuration + +
+
+ +--- + + +
Tool use: **read_file_v2** • Read file: Views/WorkerEditWindow.axaml + +
+
+ +--- + + +
+Tool use: **edit_file_v2** + + +Parameters: + +```json +{ + "relativeWorkspacePath": "Views/WorkerEditWindow.axaml" +} +``` +Additional data: + +```json +{ + "codeblockId": "371add81-871e-4ac2-bc2b-12aece92cc82" +} +``` +Status: **completed** + + +
+
+ +--- + + +
Tool use: **read_file_v2** • Read file: Views/WorkerEditWindow.axaml + +
+
+ +--- + + +Updating the ViewModel to handle empty GPU values: + + +--- + + +
Tool use: **todo_write** • Todo List + +- [x] Fix ComboBox in WorkerEditWindow.axaml to use plain strings instead of ComboBoxItem objects +- [-] Add default GPU value handling in WorkerEditViewModel.LoadWorker when GPU is empty +- [ ] Verify the GPU value is correctly saved and loaded in the configuration + +
+
+ +--- + + +
Tool use: **read_file_v2** • Read file: ViewModels/WorkerEditViewModel.cs + +
+
+ +--- + + +
+Tool use: **edit_file_v2** + + +Parameters: + +```json +{ + "relativeWorkspacePath": "ViewModels/WorkerEditViewModel.cs" +} +``` +Additional data: + +```json +{ + "codeblockId": "e3ff2d54-77b9-48d4-a21f-8163fc220400" +} +``` +Status: **completed** + + +
+
+ +--- + + +
Tool use: **todo_write** • Todo List + +- [x] Fix ComboBox in WorkerEditWindow.axaml to use plain strings instead of ComboBoxItem objects +- [x] Add default GPU value handling in WorkerEditViewModel.LoadWorker when GPU is empty +- [-] Verify the GPU value is correctly saved and loaded in the configuration + +
+
+ +--- + + +
Tool use: **read_file_v2** • Read file: Services/WorkerControllerService.cs + +
+
+ +--- + + +
+Tool use: **ripgrep_raw_search** + + +Parameters: + +```json +{ + "pattern": "sheepIt\\.Gpu|SheepIt.*Gpu", + "path": "Services", + "caseInsensitive": false +} +``` +Result: + +```json +{ + "success": { + "pattern": "sheepIt\\.Gpu|SheepIt.*Gpu", + "path": "Services", + "outputMode": "content", + "workspaceResults": { + "c:\\Users\\Nathan\\Desktop\\UFL": { + "content": { + "matches": [ + { + "file": "Services\\WorkerControllerService.cs", + "matches": [ + { + "lineNumber": 145, + "content": " '-gpu', '{sheepIt.Gpu}', '-login', '{safeUser}', '-password', '{safeKey}')" + } + ] + }, + { + "file": "Services/WorkerControllerService.cs", + "matches": [ + { + "lineNumber": 145, + "content": " '-gpu', '{sheepIt.Gpu}', '-login', '{safeUser}', '-password', '{safeKey}')" + } + ] + } + ], + "totalLines": 2, + "totalMatchedLines": 2 + } + } + } + } +} +``` +Status: **completed** + + +
+
+ +--- + + +
Tool use: **run_terminal_command_v2** • Run command: dotnet build --no-restore 2>&1 | Select-Object -First 40 + +```bash +dotnet build --no-restore 2>&1 | Select-Object -First 40 +``` + +``` + UnifiedFarmLauncher -> C:\Users\Nathan\Desktop\UFL\bin\Debug\net8.0\UnifiedFarmLauncher.dll + +Build succeeded. + 0 Warning(s) + 0 Error(s) + +Time Elapsed 00:00:00.88 + +``` +
+
+ +--- + + +Verifying the save/load flow for the GPU value: + + +--- + + +
Tool use: **read_file_v2** • Read file: ViewModels/WorkerEditViewModel.cs + +
+
+ +--- + + +
Tool use: **read_file_v2** • Read file: Services/ConfigService.cs + +
+
+ +--- + + +
Tool use: **read_file_v2** • Read file: Models/WorkerTypeConfig.cs + +
+
+ +--- + + +
Tool use: **todo_write** • Todo List + +- [x] Fix ComboBox in WorkerEditWindow.axaml to use plain strings instead of ComboBoxItem objects +- [x] Add default GPU value handling in WorkerEditViewModel.LoadWorker when GPU is empty +- [x] Verify the GPU value is correctly saved and loaded in the configuration + +
+
+ +--- + + +## Completed Changes + +1. **Fixed ComboBox binding** in `Views/WorkerEditWindow.axaml`: + - Changed from `ComboBoxItem` objects to plain `` elements + - Enables direct binding to the `SheepItGpu` string property + +2. **Added default GPU handling** in `ViewModels/WorkerEditViewModel.cs`: + - Updated `LoadWorker()` to default to "OPTIX_0" when the saved GPU value is empty or null + - Prevents the ComboBox from showin + +--- + diff --git a/ViewModels/WorkerEditViewModel.cs b/ViewModels/WorkerEditViewModel.cs index eea4cb9..a7cbce4 100644 --- a/ViewModels/WorkerEditViewModel.cs +++ b/ViewModels/WorkerEditViewModel.cs @@ -105,7 +105,9 @@ namespace UnifiedFarmLauncher.ViewModels if (worker.WorkerTypes.SheepIt != null) { HasSheepIt = true; - SheepItGpu = worker.WorkerTypes.SheepIt.Gpu; + SheepItGpu = string.IsNullOrEmpty(worker.WorkerTypes.SheepIt.Gpu) + ? "OPTIX_0" + : worker.WorkerTypes.SheepIt.Gpu; } if (worker.WorkerTypes.Flamenco != null) diff --git a/Views/WorkerEditWindow.axaml b/Views/WorkerEditWindow.axaml index 96e554c..8d9041e 100644 --- a/Views/WorkerEditWindow.axaml +++ b/Views/WorkerEditWindow.axaml @@ -36,9 +36,9 @@ - - - + OPTIX_0 + CUDA_0 + OPENCL_0