mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2025-08-20 22:32:56 +00:00
Add configuration object management for providers and chat templates
This commit is contained in:
parent
f88fdabfbe
commit
18828fbe85
@ -15,6 +15,13 @@ public sealed class PluginConfiguration(bool isInternal, LuaState state, PluginT
|
|||||||
private static readonly ILogger<PluginConfiguration> LOGGER = Program.LOGGER_FACTORY.CreateLogger<PluginConfiguration>();
|
private static readonly ILogger<PluginConfiguration> LOGGER = Program.LOGGER_FACTORY.CreateLogger<PluginConfiguration>();
|
||||||
private static readonly SettingsManager SETTINGS_MANAGER = Program.SERVICE_PROVIDER.GetRequiredService<SettingsManager>();
|
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)
|
public async Task InitializeAsync(bool dryRun)
|
||||||
{
|
{
|
||||||
if(!this.TryProcessConfiguration(dryRun, out var issue))
|
if(!this.TryProcessConfiguration(dryRun, out var issue))
|
||||||
@ -30,11 +37,13 @@ public sealed class PluginConfiguration(bool isInternal, LuaState state, PluginT
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tries to initialize the UI text content of the plugin.
|
/// Tries to initialize the UI text content of the plugin.
|
||||||
/// </summary>
|
/// </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>
|
/// <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>
|
/// <returns>True, when the UI text content could be read successfully.</returns>
|
||||||
private bool TryProcessConfiguration(bool dryRun, out string message)
|
private bool TryProcessConfiguration(bool dryRun, out string message)
|
||||||
{
|
{
|
||||||
|
this.configObjects.Clear();
|
||||||
|
|
||||||
// Ensure that the main CONFIG table exists and is a valid Lua table:
|
// Ensure that the main CONFIG table exists and is a valid Lua table:
|
||||||
if (!this.state.Environment["CONFIG"].TryRead<LuaTable>(out var mainTable))
|
if (!this.state.Environment["CONFIG"].TryRead<LuaTable>(out var mainTable))
|
||||||
{
|
{
|
||||||
@ -90,13 +99,22 @@ public sealed class PluginConfiguration(bool isInternal, LuaState state, PluginT
|
|||||||
// Apply the configured providers to the system settings:
|
// Apply the configured providers to the system settings:
|
||||||
//
|
//
|
||||||
#pragma warning disable MWAIS0001
|
#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:
|
// The iterating variable is immutable, so we need to create a local copy:
|
||||||
var provider = configuredProvider;
|
var provider = configuredProvider;
|
||||||
|
|
||||||
|
// 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);
|
var providerIndex = SETTINGS_MANAGER.ConfigurationData.Providers.FindIndex(p => p.Id == provider.Id);
|
||||||
if (providerIndex > -1)
|
if (providerIndex > -1)
|
||||||
{
|
{
|
||||||
@ -112,7 +130,7 @@ public sealed class PluginConfiguration(bool isInternal, LuaState state, PluginT
|
|||||||
SETTINGS_MANAGER.ConfigurationData.Providers.Add(provider);
|
SETTINGS_MANAGER.ConfigurationData.Providers.Add(provider);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#pragma warning restore MWAIS0001
|
#pragma warning restore MWAIS0001
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -138,12 +156,22 @@ public sealed class PluginConfiguration(bool isInternal, LuaState state, PluginT
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Apply configured chat templates to the system settings:
|
// 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:
|
// The iterating variable is immutable, so we need to create a local copy:
|
||||||
var template = configuredTemplate;
|
var template = configuredTemplate;
|
||||||
|
|
||||||
|
// Store this provider in the config object list:
|
||||||
|
this.configObjects.Add(new()
|
||||||
|
{
|
||||||
|
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);
|
var tplIndex = SETTINGS_MANAGER.ConfigurationData.ChatTemplates.FindIndex(t => t.Id == template.Id);
|
||||||
if (tplIndex > -1)
|
if (tplIndex > -1)
|
||||||
{
|
{
|
||||||
@ -160,7 +188,6 @@ public sealed class PluginConfiguration(bool isInternal, LuaState state, PluginT
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -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))
|
if (!await PLUGIN_LOAD_SEMAPHORE.WaitAsync(0, cancellationToken))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
var configObjectList = new List<PluginConfigurationObject>();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
LOG.LogInformation("Start loading plugins.");
|
LOG.LogInformation("Start loading plugins.");
|
||||||
@ -112,7 +114,8 @@ public static partial class PluginFactory
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Start or restart all plugins:
|
// Start or restart all plugins:
|
||||||
await RestartAllPlugins(cancellationToken);
|
var configObjects = await RestartAllPlugins(cancellationToken);
|
||||||
|
configObjectList.AddRange(configObjects);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@ -149,6 +152,16 @@ public static partial class PluginFactory
|
|||||||
SETTINGS_MANAGER.ConfigurationData.Providers.Remove(configuredProvider);
|
SETTINGS_MANAGER.ConfigurationData.Providers.Remove(configuredProvider);
|
||||||
wasConfigurationChanged = true;
|
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
|
#pragma warning restore MWAIS0001
|
||||||
|
|
||||||
@ -172,41 +185,17 @@ public static partial class PluginFactory
|
|||||||
SETTINGS_MANAGER.ConfigurationData.ChatTemplates.Remove(configuredTemplate);
|
SETTINGS_MANAGER.ConfigurationData.ChatTemplates.Remove(configuredTemplate);
|
||||||
wasConfigurationChanged = true;
|
wasConfigurationChanged = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
//
|
if(!configObjectList.Any(configObject =>
|
||||||
// Before checking simple settings, validate that still-present configuration plugins haven't removed individual
|
configObject.Type is PluginConfigurationObjectType.CHAT_TEMPLATE &&
|
||||||
// providers or chat templates they previously managed. If so, remove those items from our settings as well:
|
configObject.ConfigPluginId == templateSourcePluginId &&
|
||||||
//
|
configObject.Id.ToString() == configuredTemplate.Id))
|
||||||
#pragma warning disable MWAIS0001
|
|
||||||
foreach (var runningPlugin in RUNNING_PLUGINS.OfType<PluginConfiguration>())
|
|
||||||
{
|
{
|
||||||
var (providerIds, templateIds) = runningPlugin.GetManagedObjectIds();
|
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.");
|
||||||
var cfgPluginId = runningPlugin.Id;
|
SETTINGS_MANAGER.ConfigurationData.ChatTemplates.Remove(configuredTemplate);
|
||||||
|
|
||||||
// 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)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
wasConfigurationChanged = true;
|
wasConfigurationChanged = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#pragma warning restore MWAIS0001
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// ==========================================================
|
// ==========================================================
|
||||||
|
@ -11,9 +11,10 @@ public static partial class PluginFactory
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static IReadOnlyCollection<PluginBase> RunningPlugins => RUNNING_PLUGINS;
|
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.");
|
LOG.LogInformation("Try to start or restart all plugins.");
|
||||||
|
var configObjects = new List<PluginConfigurationObject>();
|
||||||
RUNNING_PLUGINS.Clear();
|
RUNNING_PLUGINS.Clear();
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -65,8 +66,13 @@ public static partial class PluginFactory
|
|||||||
{
|
{
|
||||||
if (availablePlugin.IsInternal || SETTINGS_MANAGER.IsPluginEnabled(availablePlugin) || availablePlugin.Type == PluginType.CONFIGURATION)
|
if (availablePlugin.IsInternal || SETTINGS_MANAGER.IsPluginEnabled(availablePlugin) || availablePlugin.Type == PluginType.CONFIGURATION)
|
||||||
if(await Start(availablePlugin, cancellationToken) is { IsValid: true } plugin)
|
if(await Start(availablePlugin, cancellationToken) is { IsValid: true } plugin)
|
||||||
|
{
|
||||||
|
if (plugin is PluginConfiguration configPlugin)
|
||||||
|
configObjects.AddRange(configPlugin.ConfigObjects);
|
||||||
|
|
||||||
RUNNING_PLUGINS.Add(plugin);
|
RUNNING_PLUGINS.Add(plugin);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
LOG.LogError(e, $"An error occurred while starting the plugin: Id='{availablePlugin.Id}', Type='{availablePlugin.Type}', Name='{availablePlugin.Name}', Version='{availablePlugin.Version}'.");
|
LOG.LogError(e, $"An error occurred while starting the plugin: Id='{availablePlugin.Id}', Type='{availablePlugin.Type}', Name='{availablePlugin.Name}', Version='{availablePlugin.Version}'.");
|
||||||
@ -75,6 +81,7 @@ public static partial class PluginFactory
|
|||||||
|
|
||||||
// Inform all components that the plugins have been reloaded or started:
|
// Inform all components that the plugins have been reloaded or started:
|
||||||
await MessageBus.INSTANCE.SendMessage<bool>(null, Event.PLUGINS_RELOADED);
|
await MessageBus.INSTANCE.SendMessage<bool>(null, Event.PLUGINS_RELOADED);
|
||||||
|
return configObjects;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<PluginBase> Start(IAvailablePlugin meta, CancellationToken cancellationToken = default)
|
private static async Task<PluginBase> Start(IAvailablePlugin meta, CancellationToken cancellationToken = default)
|
||||||
|
Loading…
Reference in New Issue
Block a user