From a6519ca0e246ae86907b6d429de110106bc0038e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peer=20Sch=C3=BCtt?= Date: Thu, 4 Dec 2025 15:37:13 +0100 Subject: [PATCH] Fixed a bug in GUID comparisons for configuration plugins (#578) --- .../Plugins/configuration/plugin.lua | 5 +-- .../Settings/ManagedConfiguration.Parsing.cs | 45 ++++++++++++++++++- .../Settings/SettingsManager.cs | 4 +- .../Tools/PluginSystem/PluginConfiguration.cs | 2 +- .../wwwroot/changelog/v0.9.55.md | 3 +- 5 files changed, 50 insertions(+), 9 deletions(-) diff --git a/app/MindWork AI Studio/Plugins/configuration/plugin.lua b/app/MindWork AI Studio/Plugins/configuration/plugin.lua index 77797c51..c4e5f08c 100644 --- a/app/MindWork AI Studio/Plugins/configuration/plugin.lua +++ b/app/MindWork AI Studio/Plugins/configuration/plugin.lua @@ -3,6 +3,7 @@ require("icon") -- ------ -- This is an example of a configuration plugin. Please replace -- the placeholders and assign a valid ID. +-- All IDs should be lower-case. -- ------ -- The ID for this plugin: @@ -97,9 +98,7 @@ CONFIG["SETTINGS"] = {} -- Configure the preselected profile. -- It must be one of the profile IDs defined in CONFIG["PROFILES"]. --- Be aware that the ID must be using the same casing as defined in the profile. --- When the ID is using upper case letters, but using lower case letters in this --- setting, the preselection will not work. +-- Please note: using an empty string ("") will lock the preselected profile selection, even though no valid preselected profile is found. -- CONFIG["SETTINGS"]["DataApp.PreselectedProfile"] = "00000000-0000-0000-0000-000000000000" -- Example chat templates for this configuration: diff --git a/app/MindWork AI Studio/Settings/ManagedConfiguration.Parsing.cs b/app/MindWork AI Studio/Settings/ManagedConfiguration.Parsing.cs index cbe3b968..fea31ecc 100644 --- a/app/MindWork AI Studio/Settings/ManagedConfiguration.Parsing.cs +++ b/app/MindWork AI Studio/Settings/ManagedConfiguration.Parsing.cs @@ -1,3 +1,4 @@ +using System; using System.Globalization; using System.Linq.Expressions; @@ -153,6 +154,34 @@ public static partial class ManagedConfiguration Guid configPluginId, LuaTable settings, bool dryRun) + { + return TryProcessConfiguration(configSelection, propertyExpression, string.Empty, configPluginId, settings, dryRun); + } + + /// + /// Attempts to process the configuration settings from a Lua table for string values. + /// + /// + /// When the configuration is successfully processed, it updates the configuration metadata with the configured value. + /// Furthermore, it locks the managed state of the configuration metadata to the provided configuration plugin ID. + /// The setting's value is set to the configured value. + /// + /// Parameter type of the configuration entry. + /// The ID of the related configuration plugin. + /// The Lua table containing the settings to process. + /// The expression to select the configuration class. + /// The expression to select the property within the configuration class. + /// When true, the method will not apply any changes, but only check if the configuration can be read. + /// The type of the configuration class. + /// The data type of the configured value. + /// True when the configuration was successfully processed, otherwise false. + public static bool TryProcessConfiguration( + Expression> configSelection, + Expression> propertyExpression, + TDataType configuredType, + Guid configPluginId, + LuaTable settings, + bool dryRun) { // // Handle configured string values @@ -171,8 +200,20 @@ public static partial class ManagedConfiguration // Step 2 -- try to read the Lua value as a string: if(configuredTextValue.TryRead(out var configuredText)) { - configuredValue = configuredText; - successful = true; + switch (configuredType) + { + // Case: the read string is a Guid: + case Guid: + successful = Guid.TryParse(configuredText, out var id); + configuredValue = successful ? id.ToString().ToLowerInvariant() : configuredText; + break; + + // Case: the read string is just a string: + case string: + configuredValue = configuredText; + successful = true; + break; + } } } diff --git a/app/MindWork AI Studio/Settings/SettingsManager.cs b/app/MindWork AI Studio/Settings/SettingsManager.cs index 7bab00cb..04bce7b3 100644 --- a/app/MindWork AI Studio/Settings/SettingsManager.cs +++ b/app/MindWork AI Studio/Settings/SettingsManager.cs @@ -263,7 +263,7 @@ public sealed class SettingsManager if (preselection != Profile.NO_PROFILE) return preselection; - preselection = this.ConfigurationData.Profiles.FirstOrDefault(x => x.Id == this.ConfigurationData.App.PreselectedProfile); + preselection = this.ConfigurationData.Profiles.FirstOrDefault(x => x.Id.Equals(this.ConfigurationData.App.PreselectedProfile, StringComparison.InvariantCultureIgnoreCase)); return preselection ?? Profile.NO_PROFILE; } @@ -273,7 +273,7 @@ public sealed class SettingsManager if (preselection != ChatTemplate.NO_CHAT_TEMPLATE) return preselection; - preselection = this.ConfigurationData.ChatTemplates.FirstOrDefault(x => x.Id == this.ConfigurationData.App.PreselectedChatTemplate); + preselection = this.ConfigurationData.ChatTemplates.FirstOrDefault(x => x.Id.Equals(this.ConfigurationData.App.PreselectedChatTemplate, StringComparison.InvariantCultureIgnoreCase)); return preselection ?? ChatTemplate.NO_CHAT_TEMPLATE; } diff --git a/app/MindWork AI Studio/Tools/PluginSystem/PluginConfiguration.cs b/app/MindWork AI Studio/Tools/PluginSystem/PluginConfiguration.cs index 979a626a..afa97c14 100644 --- a/app/MindWork AI Studio/Tools/PluginSystem/PluginConfiguration.cs +++ b/app/MindWork AI Studio/Tools/PluginSystem/PluginConfiguration.cs @@ -77,7 +77,7 @@ public sealed class PluginConfiguration(bool isInternal, LuaState state, PluginT PluginConfigurationObject.TryParse(PluginConfigurationObjectType.PROFILE, x => x.Profiles, x => x.NextProfileNum, mainTable, this.Id, ref this.configObjects, dryRun); // Config: preselected profile? - ManagedConfiguration.TryProcessConfiguration(x => x.App, x => x.PreselectedProfile, this.Id, settingsTable, dryRun); + ManagedConfiguration.TryProcessConfiguration(x => x.App, x => x.PreselectedProfile, Guid.Empty, this.Id, settingsTable, dryRun); message = string.Empty; return true; diff --git a/app/MindWork AI Studio/wwwroot/changelog/v0.9.55.md b/app/MindWork AI Studio/wwwroot/changelog/v0.9.55.md index 9ee51756..321f7bbb 100644 --- a/app/MindWork AI Studio/wwwroot/changelog/v0.9.55.md +++ b/app/MindWork AI Studio/wwwroot/changelog/v0.9.55.md @@ -1,2 +1,3 @@ # v0.9.55, build 230 (2025-12-xx xx:xx UTC) -- Added support for newer Mistral models (Mistral 3, Voxtral, and Magistral) \ No newline at end of file +- Added support for newer Mistral models (Mistral 3, Voxtral, and Magistral). +- Improved the ID handling for configuration plugins. \ No newline at end of file