mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2025-08-20 11:32:57 +00:00
Add configuration object management for providers and chat templates
This commit is contained in:
parent
f88fdabfbe
commit
18828fbe85
@ -14,7 +14,14 @@ public sealed class PluginConfiguration(bool isInternal, LuaState state, PluginT
|
||||
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(PluginConfiguration).Namespace, nameof(PluginConfiguration));
|
||||
private static readonly ILogger<PluginConfiguration> LOGGER = Program.LOGGER_FACTORY.CreateLogger<PluginConfiguration>();
|
||||
private static readonly SettingsManager SETTINGS_MANAGER = Program.SERVICE_PROVIDER.GetRequiredService<SettingsManager>();
|
||||
|
||||
|
||||
private readonly List<PluginConfigurationObject> configObjects = [];
|
||||
|
||||
/// <summary>
|
||||
/// The list of configuration objects. Configuration objects are, e.g., providers or chat templates.
|
||||
/// </summary>
|
||||
public IEnumerable<PluginConfigurationObject> ConfigObjects => this.configObjects;
|
||||
|
||||
public async Task InitializeAsync(bool dryRun)
|
||||
{
|
||||
if(!this.TryProcessConfiguration(dryRun, out var issue))
|
||||
@ -30,11 +37,13 @@ public sealed class PluginConfiguration(bool isInternal, LuaState state, PluginT
|
||||
/// <summary>
|
||||
/// Tries to initialize the UI text content of the plugin.
|
||||
/// </summary>
|
||||
/// <param name="dryRun">When true, the method will not apply any changes, but only check if the configuration can be read.</param>
|
||||
/// <param name="dryRun">When true, the method will not apply any changes but only check if the configuration can be read.</param>
|
||||
/// <param name="message">The error message, when the UI text content could not be read.</param>
|
||||
/// <returns>True, when the UI text content could be read successfully.</returns>
|
||||
private bool TryProcessConfiguration(bool dryRun, out string message)
|
||||
{
|
||||
this.configObjects.Clear();
|
||||
|
||||
// Ensure that the main CONFIG table exists and is a valid Lua table:
|
||||
if (!this.state.Environment["CONFIG"].TryRead<LuaTable>(out var mainTable))
|
||||
{
|
||||
@ -90,29 +99,38 @@ public sealed class PluginConfiguration(bool isInternal, LuaState state, PluginT
|
||||
// Apply the configured providers to the system settings:
|
||||
//
|
||||
#pragma warning disable MWAIS0001
|
||||
if (!dryRun)
|
||||
foreach (var configuredProvider in configuredProviders)
|
||||
{
|
||||
foreach (var configuredProvider in configuredProviders)
|
||||
{
|
||||
// The iterating variable is immutable, so we need to create a local copy:
|
||||
var provider = configuredProvider;
|
||||
// The iterating variable is immutable, so we need to create a local copy:
|
||||
var provider = configuredProvider;
|
||||
|
||||
var providerIndex = SETTINGS_MANAGER.ConfigurationData.Providers.FindIndex(p => p.Id == provider.Id);
|
||||
if (providerIndex > -1)
|
||||
{
|
||||
// Case: The provider already exists, we update it:
|
||||
var existingProvider = SETTINGS_MANAGER.ConfigurationData.Providers[providerIndex];
|
||||
provider = provider with { Num = existingProvider.Num }; // Keep the original number
|
||||
SETTINGS_MANAGER.ConfigurationData.Providers[providerIndex] = provider;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Case: The provider does not exist, we add it:
|
||||
provider = provider with { Num = SETTINGS_MANAGER.ConfigurationData.NextProviderNum++ };
|
||||
SETTINGS_MANAGER.ConfigurationData.Providers.Add(provider);
|
||||
}
|
||||
// Store this provider in the config object list:
|
||||
this.configObjects.Add(new()
|
||||
{
|
||||
ConfigPluginId = this.Id,
|
||||
Id = Guid.Parse(provider.Id),
|
||||
Type = PluginConfigurationObjectType.LLM_PROVIDER,
|
||||
});
|
||||
|
||||
if (dryRun)
|
||||
continue;
|
||||
|
||||
var providerIndex = SETTINGS_MANAGER.ConfigurationData.Providers.FindIndex(p => p.Id == provider.Id);
|
||||
if (providerIndex > -1)
|
||||
{
|
||||
// Case: The provider already exists, we update it:
|
||||
var existingProvider = SETTINGS_MANAGER.ConfigurationData.Providers[providerIndex];
|
||||
provider = provider with { Num = existingProvider.Num }; // Keep the original number
|
||||
SETTINGS_MANAGER.ConfigurationData.Providers[providerIndex] = provider;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Case: The provider does not exist, we add it:
|
||||
provider = provider with { Num = SETTINGS_MANAGER.ConfigurationData.NextProviderNum++ };
|
||||
SETTINGS_MANAGER.ConfigurationData.Providers.Add(provider);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore MWAIS0001
|
||||
|
||||
//
|
||||
@ -138,26 +156,35 @@ public sealed class PluginConfiguration(bool isInternal, LuaState state, PluginT
|
||||
}
|
||||
|
||||
// Apply configured chat templates to the system settings:
|
||||
if (!dryRun)
|
||||
foreach (var configuredTemplate in configuredTemplates)
|
||||
{
|
||||
foreach (var configuredTemplate in configuredTemplates)
|
||||
// The iterating variable is immutable, so we need to create a local copy:
|
||||
var template = configuredTemplate;
|
||||
|
||||
// Store this provider in the config object list:
|
||||
this.configObjects.Add(new()
|
||||
{
|
||||
// The iterating variable is immutable, so we need to create a local copy:
|
||||
var template = configuredTemplate;
|
||||
var tplIndex = SETTINGS_MANAGER.ConfigurationData.ChatTemplates.FindIndex(t => t.Id == template.Id);
|
||||
if (tplIndex > -1)
|
||||
{
|
||||
// Case: The template already exists, we update it:
|
||||
var existingTemplate = SETTINGS_MANAGER.ConfigurationData.ChatTemplates[tplIndex];
|
||||
template = template with { Num = existingTemplate.Num };
|
||||
SETTINGS_MANAGER.ConfigurationData.ChatTemplates[tplIndex] = template;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Case: The template does not exist, we add it:
|
||||
template = template with { Num = SETTINGS_MANAGER.ConfigurationData.NextChatTemplateNum++ };
|
||||
SETTINGS_MANAGER.ConfigurationData.ChatTemplates.Add(template);
|
||||
}
|
||||
ConfigPluginId = this.Id,
|
||||
Id = Guid.Parse(template.Id),
|
||||
Type = PluginConfigurationObjectType.CHAT_TEMPLATE,
|
||||
});
|
||||
|
||||
if (dryRun)
|
||||
continue;
|
||||
|
||||
var tplIndex = SETTINGS_MANAGER.ConfigurationData.ChatTemplates.FindIndex(t => t.Id == template.Id);
|
||||
if (tplIndex > -1)
|
||||
{
|
||||
// Case: The template already exists, we update it:
|
||||
var existingTemplate = SETTINGS_MANAGER.ConfigurationData.ChatTemplates[tplIndex];
|
||||
template = template with { Num = existingTemplate.Num };
|
||||
SETTINGS_MANAGER.ConfigurationData.ChatTemplates[tplIndex] = template;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Case: The template does not exist, we add it:
|
||||
template = template with { Num = SETTINGS_MANAGER.ConfigurationData.NextChatTemplateNum++ };
|
||||
SETTINGS_MANAGER.ConfigurationData.ChatTemplates.Add(template);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,23 @@
|
||||
namespace AIStudio.Tools.PluginSystem;
|
||||
|
||||
/// <summary>
|
||||
/// Represents metadata for a configuration object from a configuration plugin. These are
|
||||
/// complex objects such as configured LLM providers, chat templates, etc.
|
||||
/// </summary>
|
||||
public sealed record PluginConfigurationObject
|
||||
{
|
||||
/// <summary>
|
||||
/// The id of the configuration plugin to which this configuration object belongs.
|
||||
/// </summary>
|
||||
public required Guid ConfigPluginId { get; init; } = Guid.NewGuid();
|
||||
|
||||
/// <summary>
|
||||
/// The id of the configuration object, e.g., the id of a chat template.
|
||||
/// </summary>
|
||||
public required Guid Id { get; init; } = Guid.NewGuid();
|
||||
|
||||
/// <summary>
|
||||
/// The type of the configuration object.
|
||||
/// </summary>
|
||||
public required PluginConfigurationObjectType Type { get; init; } = PluginConfigurationObjectType.NONE;
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
namespace AIStudio.Tools.PluginSystem;
|
||||
|
||||
public enum PluginConfigurationObjectType
|
||||
{
|
||||
NONE,
|
||||
UNKNOWN,
|
||||
|
||||
PROFILE,
|
||||
DATA_SOURCE,
|
||||
LLM_PROVIDER,
|
||||
CHAT_TEMPLATE,
|
||||
EMBEDDING_PROVIDER,
|
||||
}
|
@ -40,6 +40,8 @@ public static partial class PluginFactory
|
||||
if (!await PLUGIN_LOAD_SEMAPHORE.WaitAsync(0, cancellationToken))
|
||||
return;
|
||||
|
||||
var configObjectList = new List<PluginConfigurationObject>();
|
||||
|
||||
try
|
||||
{
|
||||
LOG.LogInformation("Start loading plugins.");
|
||||
@ -112,7 +114,8 @@ public static partial class PluginFactory
|
||||
}
|
||||
|
||||
// Start or restart all plugins:
|
||||
await RestartAllPlugins(cancellationToken);
|
||||
var configObjects = await RestartAllPlugins(cancellationToken);
|
||||
configObjectList.AddRange(configObjects);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@ -149,6 +152,16 @@ public static partial class PluginFactory
|
||||
SETTINGS_MANAGER.ConfigurationData.Providers.Remove(configuredProvider);
|
||||
wasConfigurationChanged = true;
|
||||
}
|
||||
|
||||
if(!configObjectList.Any(configObject =>
|
||||
configObject.Type is PluginConfigurationObjectType.LLM_PROVIDER &&
|
||||
configObject.ConfigPluginId == providerSourcePluginId &&
|
||||
configObject.Id.ToString() == configuredProvider.Id))
|
||||
{
|
||||
LOG.LogWarning($"The configured LLM provider '{configuredProvider.InstanceName}' (id={configuredProvider.Id}) is not present in the configuration plugin anymore. Removing the provider from the settings.");
|
||||
SETTINGS_MANAGER.ConfigurationData.Providers.Remove(configuredProvider);
|
||||
wasConfigurationChanged = true;
|
||||
}
|
||||
}
|
||||
#pragma warning restore MWAIS0001
|
||||
|
||||
@ -172,41 +185,17 @@ public static partial class PluginFactory
|
||||
SETTINGS_MANAGER.ConfigurationData.ChatTemplates.Remove(configuredTemplate);
|
||||
wasConfigurationChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Before checking simple settings, validate that still-present configuration plugins haven't removed individual
|
||||
// providers or chat templates they previously managed. If so, remove those items from our settings as well:
|
||||
//
|
||||
#pragma warning disable MWAIS0001
|
||||
foreach (var runningPlugin in RUNNING_PLUGINS.OfType<PluginConfiguration>())
|
||||
{
|
||||
var (providerIds, templateIds) = runningPlugin.GetManagedObjectIds();
|
||||
var cfgPluginId = runningPlugin.Id;
|
||||
|
||||
// Providers managed by this plugin but no longer present in plugin config
|
||||
var providersToRemove = SETTINGS_MANAGER.ConfigurationData.Providers
|
||||
.Where(p => p.IsEnterpriseConfiguration && p.EnterpriseConfigurationPluginId == cfgPluginId && !providerIds.Contains(p.Id))
|
||||
.ToList();
|
||||
foreach (var p in providersToRemove)
|
||||
|
||||
if(!configObjectList.Any(configObject =>
|
||||
configObject.Type is PluginConfigurationObjectType.CHAT_TEMPLATE &&
|
||||
configObject.ConfigPluginId == templateSourcePluginId &&
|
||||
configObject.Id.ToString() == configuredTemplate.Id))
|
||||
{
|
||||
LOG.LogWarning($"The configured LLM provider '{p.InstanceName}' (id={p.Id}) was removed from its configuration plugin (id={cfgPluginId}). Removing the provider from the settings.");
|
||||
SETTINGS_MANAGER.ConfigurationData.Providers.Remove(p);
|
||||
wasConfigurationChanged = true;
|
||||
}
|
||||
|
||||
// Chat templates managed by this plugin but no longer present in plugin config
|
||||
var templatesToRemove = SETTINGS_MANAGER.ConfigurationData.ChatTemplates
|
||||
.Where(t => t.IsEnterpriseConfiguration && t.EnterpriseConfigurationPluginId == cfgPluginId && !templateIds.Contains(t.Id))
|
||||
.ToList();
|
||||
foreach (var t in templatesToRemove)
|
||||
{
|
||||
LOG.LogWarning($"The configured chat template '{t.Name}' (id={t.Id}) was removed from its configuration plugin (id={cfgPluginId}). Removing the chat template from the settings.");
|
||||
SETTINGS_MANAGER.ConfigurationData.ChatTemplates.Remove(t);
|
||||
LOG.LogWarning($"The configured chat template '{configuredTemplate.Name}' (id={configuredTemplate.Id}) is not present in the configuration plugin anymore. Removing the chat template from the settings.");
|
||||
SETTINGS_MANAGER.ConfigurationData.ChatTemplates.Remove(configuredTemplate);
|
||||
wasConfigurationChanged = true;
|
||||
}
|
||||
}
|
||||
#pragma warning restore MWAIS0001
|
||||
|
||||
//
|
||||
// ==========================================================
|
||||
|
@ -11,9 +11,10 @@ public static partial class PluginFactory
|
||||
/// </summary>
|
||||
public static IReadOnlyCollection<PluginBase> RunningPlugins => RUNNING_PLUGINS;
|
||||
|
||||
private static async Task RestartAllPlugins(CancellationToken cancellationToken = default)
|
||||
private static async Task<List<PluginConfigurationObject>> RestartAllPlugins(CancellationToken cancellationToken = default)
|
||||
{
|
||||
LOG.LogInformation("Try to start or restart all plugins.");
|
||||
var configObjects = new List<PluginConfigurationObject>();
|
||||
RUNNING_PLUGINS.Clear();
|
||||
|
||||
//
|
||||
@ -65,7 +66,12 @@ public static partial class PluginFactory
|
||||
{
|
||||
if (availablePlugin.IsInternal || SETTINGS_MANAGER.IsPluginEnabled(availablePlugin) || availablePlugin.Type == PluginType.CONFIGURATION)
|
||||
if(await Start(availablePlugin, cancellationToken) is { IsValid: true } plugin)
|
||||
{
|
||||
if (plugin is PluginConfiguration configPlugin)
|
||||
configObjects.AddRange(configPlugin.ConfigObjects);
|
||||
|
||||
RUNNING_PLUGINS.Add(plugin);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@ -75,6 +81,7 @@ public static partial class PluginFactory
|
||||
|
||||
// Inform all components that the plugins have been reloaded or started:
|
||||
await MessageBus.INSTANCE.SendMessage<bool>(null, Event.PLUGINS_RELOADED);
|
||||
return configObjects;
|
||||
}
|
||||
|
||||
private static async Task<PluginBase> Start(IAvailablePlugin meta, CancellationToken cancellationToken = default)
|
||||
|
Loading…
Reference in New Issue
Block a user