mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-08-11 18:32:12 +00:00
Fixed deleting assistant plugins which the Assistant Builder did not create
This commit is contained in:
parent
eeb890f8f1
commit
b45f55cfe1
@ -109,6 +109,34 @@ public static partial class PluginFactory
|
||||
/// <returns>True when the directory is nested in the plugins directory.</returns>
|
||||
public static bool IsInsidePluginsRoot(string? pluginPath) => IsPathInside(PLUGINS_ROOT, pluginPath);
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether a plugin directory is the plugins directory itself.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A `plugin.lua` placed directly in the plugins directory makes that directory the plugin
|
||||
/// directory. Removing or replacing such a plugin means touching its directory, which would take
|
||||
/// every other plugin with it.
|
||||
/// </remarks>
|
||||
/// <param name="pluginPath">The directory of the plugin.</param>
|
||||
/// <returns>True when the directory is the plugins directory.</returns>
|
||||
public static bool IsPluginsRoot(string? pluginPath)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(pluginPath) || string.IsNullOrWhiteSpace(PLUGINS_ROOT))
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
var root = Path.GetFullPath(PLUGINS_ROOT).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
||||
var pluginDirectory = Path.GetFullPath(pluginPath).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
||||
return string.Equals(root, pluginDirectory, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.LogWarning(e, $"Was not able to check whether the plugin directory '{pluginPath}' is the plugins directory. Treating it as the plugins directory.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsPathInside(string rootDirectory, string? pluginPath)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(pluginPath) || string.IsNullOrWhiteSpace(rootDirectory))
|
||||
|
||||
@ -9,16 +9,16 @@ namespace AIStudio.Tools.Services;
|
||||
public sealed partial class PluginInstallService
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks whether a local plugin is an Assistant Builder generated assistant that users may delete.
|
||||
/// Checks whether an assistant plugin is one that users may delete.
|
||||
/// </summary>
|
||||
public static bool CanDeleteInstalledAssistant(IAvailablePlugin plugin) => string.IsNullOrWhiteSpace(GetAssistantDeletionEligibilityIssue(plugin));
|
||||
|
||||
/// <summary>
|
||||
/// The plugin types users may remove through the user interface, besides their own assistants.
|
||||
/// The plugin types users may remove through the user interface, besides assistants.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Assistants have their own path, because only those generated by the Assistant Builder may be
|
||||
/// deleted and because a running assistant must not be pulled away from under a user.
|
||||
/// Assistants have their own path, because a running assistant must not be pulled away from
|
||||
/// under a user and because removing one also removes its security audit.
|
||||
/// </remarks>
|
||||
private static readonly PluginType[] DELETABLE_LOCAL_PLUGIN_TYPES = [PluginType.CONFIGURATION, PluginType.LANGUAGE];
|
||||
|
||||
@ -229,27 +229,22 @@ public sealed partial class PluginInstallService
|
||||
if (plugin.IsInternal)
|
||||
return TB("Internal assistant plugins cannot be deleted.");
|
||||
|
||||
if (plugin.IsManagedByConfigServer)
|
||||
return TB("Config Server managed assistant plugins cannot be deleted.");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(plugin.LocalPath))
|
||||
return TB("The assistant plugin has no local directory.");
|
||||
|
||||
var assistantPlugin = PluginFactory.RunningPlugins
|
||||
.OfType<PluginAssistants>()
|
||||
.FirstOrDefault(candidate => candidate.Id == plugin.Id && IsSameDirectory(candidate.PluginPath, plugin.LocalPath));
|
||||
|
||||
if (assistantPlugin is null || assistantPlugin.IsInternal || !assistantPlugin.IsAssistantBuilderGenerated)
|
||||
return TB("Only assistants generated by the Assistant Builder can be deleted.");
|
||||
|
||||
if (assistantPlugin.IsManagedByConfigServer)
|
||||
//
|
||||
// Like for every other plugin type, the plugin path decides, not what the plugin declares
|
||||
// about itself. Neither DEPLOYED_USING_CONFIG_SERVER nor the Assistant Builder metadata is
|
||||
// suitable here: a locally placed assistant could declare itself as deployed by an
|
||||
// organization, or simply omit the builder metadata, and would then be impossible to remove
|
||||
// through the user interface. Editing, revising, and sharing an assistant already follow the
|
||||
// path, so deleting one must not be the single action that trusts the plugin's own claims.
|
||||
//
|
||||
if (PluginFactory.IsEnterpriseConfigurationPath(plugin.LocalPath))
|
||||
return TB("Config Server managed assistant plugins cannot be deleted.");
|
||||
|
||||
if (!TryGetPluginRoot(PluginType.ASSISTANT, out var assistantPluginsRoot, out var rootIssue))
|
||||
return rootIssue;
|
||||
|
||||
if (!IsPathInsideDirectory(assistantPluginsRoot, plugin.LocalPath) || IsSameDirectory(assistantPluginsRoot, plugin.LocalPath))
|
||||
return TB("The assistant plugin directory is outside the local assistant plugin directory.");
|
||||
if (!PluginFactory.IsInsidePluginsRoot(plugin.LocalPath) || PluginFactory.IsPluginsRoot(plugin.LocalPath))
|
||||
return TB("The assistant plugin directory is outside the plugins directory.");
|
||||
|
||||
return Directory.Exists(plugin.LocalPath)
|
||||
? string.Empty
|
||||
@ -276,7 +271,7 @@ public sealed partial class PluginInstallService
|
||||
if (PluginFactory.IsEnterpriseConfigurationPath(plugin.LocalPath))
|
||||
return TB("Plugins deployed by your organization cannot be deleted.");
|
||||
|
||||
if (!PluginFactory.IsInsidePluginsRoot(plugin.LocalPath))
|
||||
if (!PluginFactory.IsInsidePluginsRoot(plugin.LocalPath) || PluginFactory.IsPluginsRoot(plugin.LocalPath))
|
||||
return TB("The plugin directory is outside the plugins directory.");
|
||||
|
||||
return Directory.Exists(plugin.LocalPath)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user