using AIStudio.Settings;
using AIStudio.Tools.AssistantSessions;
using AIStudio.Tools.PluginSystem;
using AIStudio.Tools.PluginSystem.Assistants;
namespace AIStudio.Tools.Services;
///
/// Installs, updates, and removes the plugins AI Studio manages locally.
///
///
/// The implementation is split across several files:
/// - PluginInstallService.AssistantBuilder.cs: installing generated assistant plugin code
/// - PluginInstallService.Editing.cs: editing an installed assistant plugin
/// - PluginInstallService.Import.cs: importing plugin archives
/// - PluginInstallService.Delete.cs: removing installed plugins
/// - PluginInstallService.Installation.cs: the shared validation and installation steps
/// - PluginInstallService.FileSystem.cs: the shared path and directory helpers
///
public sealed partial class PluginInstallService
{
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(PluginInstallService).Namespace, nameof(PluginInstallService));
private const string PLUGIN_FILE_NAME = "plugin.lua";
private const string ASSISTANT_BUILDER_DIRECTORY_PREFIX = "assistant-builder";
private const string DELETE_BACKUP_DIRECTORY = ".plugin-delete-backups";
private const string INSTALL_BACKUP_DIRECTORY = ".plugin-install-backups";
private const int DIRECTORY_PREFIX_MAX_LEN = 80;
private readonly ILogger logger;
private readonly SettingsManager settingsManager;
private readonly AssistantSessionService assistantSessionService;
private readonly MediaTranscriptionService mediaTranscriptionService;
private readonly SemaphoreSlim installSemaphore = new(1, 1);
private static AssistantPluginInstallResult Error(string issue) => new(false, Guid.Empty, string.Empty, string.Empty, false, issue);
private static AssistantPluginInstallResult CancelledByUser() => new(false, Guid.Empty, string.Empty, string.Empty, false, string.Empty, true);
private static AssistantPluginCheckResult CheckError(string issue) => new(false, Guid.Empty, string.Empty, issue);
private static PluginDeleteResult DeleteError(IPluginMetadata plugin, string pluginDirectory, string issue) => new(false, plugin.Id, plugin.Name, pluginDirectory, issue);
private static AssistantPluginUpdateResult UpdateError(IPluginMetadata plugin, string pluginDirectory, string issue) => new(false, plugin.Id, plugin.Name, pluginDirectory, issue);
public PluginInstallService(ILogger logger, SettingsManager settingsManager, AssistantSessionService assistantSessionService, MediaTranscriptionService mediaTranscriptionService)
{
this.logger = logger;
this.settingsManager = settingsManager;
this.assistantSessionService = assistantSessionService;
this.mediaTranscriptionService = mediaTranscriptionService;
this.logger.LogInformation("The plugin install service has been initialized.");
}
private sealed record PluginValidationResult(bool Success, string StagingDirectory, PluginBase? Plugin, string Issue)
{
public static PluginValidationResult Failure(string issue) => new(false, string.Empty, null, issue);
///
/// The validated plugin as an assistant plugin, or null when it has another type.
///
public PluginAssistants? AssistantPlugin => this.Plugin as PluginAssistants;
}
}