using System.Linq.Expressions; using AIStudio.Settings; using AIStudio.Settings.DataModel; namespace AIStudio.Tools.PluginSystem; /// /// Represents metadata for a configuration object from a configuration plugin. These are /// complex objects such as configured LLM providers, chat templates, etc. /// public sealed record PluginConfigurationObject { private static readonly SettingsManager SETTINGS_MANAGER = Program.SERVICE_PROVIDER.GetRequiredService(); private static readonly ILogger LOG = Program.LOGGER_FACTORY.CreateLogger(); /// /// The id of the configuration plugin to which this configuration object belongs. /// public required Guid ConfigPluginId { get; init; } = Guid.NewGuid(); /// /// The id of the configuration object, e.g., the id of a chat template. /// public required Guid Id { get; init; } = Guid.NewGuid(); /// /// The type of the configuration object. /// public required PluginConfigurationObjectType Type { get; init; } = PluginConfigurationObjectType.NONE; /// /// Cleans up configuration objects of a specified type that are no longer associated with any available plugin. /// /// The type of configuration object to clean up. /// The type of configuration object to process. /// A selection expression to retrieve the configuration objects from the main configuration. /// A list of currently available plugins. /// A list of all existing configuration objects. /// Returns true if the configuration was altered during cleanup; otherwise, false. public static bool CleanLeftOverConfigurationObjects( PluginConfigurationObjectType configObjectType, Expression>> configObjectSelection, IList availablePlugins, IList configObjectList) where TClass : IConfigurationObject { var configuredObjects = configObjectSelection.Compile()(SETTINGS_MANAGER.ConfigurationData); var leftOverObjects = new List(); foreach (var configuredObject in configuredObjects) { if(!configuredObject.IsEnterpriseConfiguration) continue; var configObjectSourcePluginId = configuredObject.EnterpriseConfigurationPluginId; if(configObjectSourcePluginId == Guid.Empty) continue; var templateSourcePlugin = availablePlugins.FirstOrDefault(plugin => plugin.Id == configObjectSourcePluginId); if(templateSourcePlugin is null) { LOG.LogWarning($"The configured object '{configuredObject.Name}' (id={configuredObject.Id}) is based on a plugin that is not available anymore. Removing the chat template from the settings."); leftOverObjects.Add(configuredObject); } if(!configObjectList.Any(configObject => configObject.Type == configObjectType && configObject.ConfigPluginId == configObjectSourcePluginId && configObject.Id.ToString() == configuredObject.Id)) { LOG.LogWarning($"The configured object '{configuredObject.Name}' (id={configuredObject.Id}) is not present in the configuration plugin anymore. Removing the chat template from the settings."); leftOverObjects.Add(configuredObject); } } // Remove collected items after enumeration to avoid modifying the collection during iteration: var wasConfigurationChanged = leftOverObjects.Count > 0; foreach (var item in leftOverObjects.Distinct()) configuredObjects.Remove(item); return wasConfigurationChanged; } }