Fixed accepting assistant plugins that use the ID of another plugin

This commit is contained in:
Thorsten Sommer 2026-08-06 08:50:18 +02:00
parent 9cbf0c1256
commit cb00005fbd
Signed by untrusted user who does not match committer: tsommer
GPG Key ID: 371BBA77A02C0108

View File

@ -182,7 +182,7 @@ public sealed class AssistantPluginInstallService
pluginCode.Trim(), pluginCode.Trim(),
TB("Currently, only assistant plugins can be imported."), TB("Currently, only assistant plugins can be imported."),
TB("The imported assistant plugin is invalid. Issue: {0}"), TB("The imported assistant plugin is invalid. Issue: {0}"),
TB("The imported assistant plugin uses the ID of an internal AI Studio plugin."), TB("The imported assistant plugin uses the ID of another installed plugin."),
token); token);
if (!validation.Success || validation.AssistantPlugin is null) if (!validation.Success || validation.AssistantPlugin is null)
@ -528,7 +528,7 @@ public sealed class AssistantPluginInstallService
pluginCode, pluginCode,
TB("The generated plugin is not an assistant plugin. Issue: {0}"), TB("The generated plugin is not an assistant plugin. Issue: {0}"),
TB("The generated assistant plugin is invalid. Issue: {0}"), TB("The generated assistant plugin is invalid. Issue: {0}"),
TB("The generated assistant plugin uses the ID of an internal AI Studio plugin."), TB("The generated assistant plugin uses the ID of another installed plugin."),
token); token);
if (!validation.Success || validation.AssistantPlugin is null) if (!validation.Success || validation.AssistantPlugin is null)
@ -559,7 +559,7 @@ public sealed class AssistantPluginInstallService
lua.Trim(), lua.Trim(),
TB("The edited plugin is not an assistant plugin. Issue: {0}"), TB("The edited plugin is not an assistant plugin. Issue: {0}"),
TB("The edited assistant plugin is invalid. Issue: {0}"), TB("The edited assistant plugin is invalid. Issue: {0}"),
TB("The edited assistant plugin uses the ID of an internal AI Studio plugin."), TB("The edited assistant plugin uses the ID of another installed plugin."),
token); token);
} }
catch (Exception e) catch (Exception e)
@ -570,7 +570,7 @@ public sealed class AssistantPluginInstallService
} }
private static async Task<AssistantPluginValidationResult> ValidateAssistantPluginCodeAsync(string pluginDirectory, string pluginCode, private static async Task<AssistantPluginValidationResult> ValidateAssistantPluginCodeAsync(string pluginDirectory, string pluginCode,
string notAssistantIssue, string invalidAssistantIssue, string internalPluginIdIssue, CancellationToken token) string notAssistantIssue, string invalidAssistantIssue, string conflictingPluginIdIssue, CancellationToken token)
{ {
// The plugin is not installed yet: it sits in a staging directory outside the installed // The plugin is not installed yet: it sits in a staging directory outside the installed
// plugins directory. We allow that directory as the module base, so the plugin can load its // plugins directory. We allow that directory as the module base, so the plugin can load its
@ -582,8 +582,12 @@ public sealed class AssistantPluginInstallService
if (!assistantPlugin.IsValid) if (!assistantPlugin.IsValid)
return AssistantPluginValidationResult.Failure(string.Format(invalidAssistantIssue, string.Join("; ", assistantPlugin.Issues))); return AssistantPluginValidationResult.Failure(string.Format(invalidAssistantIssue, string.Join("; ", assistantPlugin.Issues)));
if (PluginFactory.AvailablePlugins.Any(availablePlugin => availablePlugin.Type is PluginType.ASSISTANT && availablePlugin.Id == assistantPlugin.Id && availablePlugin.IsInternal)) // Plugin IDs must be unique across all plugin types: several lookups resolve a plugin by its
return AssistantPluginValidationResult.Failure(internalPluginIdIssue); // ID alone, e.g., the base language plugin in PluginFactory.Starting. An assistant plugin
// carrying the ID of a language or configuration plugin would break those lookups. Reusing
// the ID of another local assistant plugin stays allowed: that is how updating one works.
if (PluginFactory.AvailablePlugins.Any(availablePlugin => availablePlugin.Id == assistantPlugin.Id && (availablePlugin.IsInternal || availablePlugin.Type is not PluginType.ASSISTANT)))
return AssistantPluginValidationResult.Failure(conflictingPluginIdIssue);
return new(true, string.Empty, assistantPlugin, string.Empty); return new(true, string.Empty, assistantPlugin, string.Empty);
} }