diff --git a/CHANGELOG.md b/CHANGELOG.md index a0b37acf..764ee032 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to Stability Matrix will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2.0.0.html). +## v2.2.1 +### Fixed +- Fixed SD.Next shared folders config not working with new config format, reverted to Junctions / Symlinks + ## v2.2.0 ### Added - Added option to search by Base Model in the Model Browser @@ -13,6 +17,7 @@ and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2 ### Fixed - Fixed [#59](https://github.com/LykosAI/StabilityMatrix/issues/61) - `GIT` environment variable is now set for the embedded portable git on Windows as A1111 uses it instead of default `PATH` resolution - Fixed embedded Python install check on Linux when an incompatible windows DLL is in the Python install directory +- Fixed "ObjectDisposed" database errors that sometimes appeared when closing the app ### Changed - Revamped Package Manager UI diff --git a/README.md b/README.md index aa94df23..5c2c9897 100644 --- a/README.md +++ b/README.md @@ -7,14 +7,29 @@ [download-win-x64]: https://github.com/LykosAI/StabilityMatrix/releases/latest/download/StabilityMatrix-win-x64.zip [download-linux-x64]: https://github.com/LykosAI/StabilityMatrix/releases/latest/download/StabilityMatrix-linux-x64.zip [download-macos]: https://github.com/LykosAI/StabilityMatrix/issues/45 + [auto1111]: https://github.com/AUTOMATIC1111/stable-diffusion-webui [comfy]: https://github.com/comfyanonymous/ComfyUI [sdnext]: https://github.com/vladmandic/automatic +[voltaml]: https://github.com/VoltaML/voltaML-fast-stable-diffusion +[invokeai]: https://github.com/invoke-ai/InvokeAI + +[civitai]: https://civitai.com/ Multi-Platform Package Manager for Stable Diffusion -- One click install and update for Stable Diffusion Web UIs - - Currently supports [Automatic 1111][auto1111], [Comfy UI][comfy], [SD.Next (Vladmandic)][sdnext], with more planned -- Shared checkpoint manager with browsable imports from CivitAI + +### 🖱️ One click install and update for Stable Diffusion Web UI Packages +- Supports [Automatic 1111][auto1111], [Comfy UI][comfy], [SD.Next (Vladmandic)][sdnext], [VoltaML][voltaml], [InvokeAI][invokeai] +- Embedded Git and Python dependencies, with no need for either to be globally installed +- Fully Portable, move Stability Matrix's Data Directory to a new drive or computer at any time +### 🚀 Launcher with syntax highlighted terminal emulator, routed GUI input prompts +- Launch arguments editor with predefined or custom options for each Package install +- Package environment variables +### 🗃️ Checkpoint Manager, configured to be shared by all Package installs +- Option to find CivitAI metadata and preview thumbnails for new local imports +### ☁️ Model Browser to import from [CivitAI][civitai] +- Automatically imports to the associated model folder depending on the model type +- Also downloads relavent metadata files and preview image ![header](https://github.com/LykosAI/StabilityMatrix/assets/13956642/a9c5f925-8561-49ba-855b-1b7bf57d7c0d) @@ -26,22 +41,17 @@ Multi-Platform Package Manager for Stable Diffusion > macOS builds are currently pending: [#45][download-macos] -## Features -- Launcher with syntax highlighted terminal emulator, launch arguments support -- Portable embedded dependencies and frameworks (like Git and Python) with no required changes to global installs. -- Virtual environment management using [Python.NET](https://github.com/pythonnet/pythonnet) - ### Searchable launch options

- +

-### Model browser powered by [Civit AI](https://civitai.com/) - +### Model browser powered by [Civit AI][civitai] - Downloads new models, automatically uses the appropriate shared model directory - Available immediately to all installed packages +

- +

### Shared model directory for all your packages @@ -50,7 +60,7 @@ Multi-Platform Package Manager for Stable Diffusion - Toggle visibility of categories like LoRA, VAE, CLIP, etc. - For models imported from Civit AI, shows additional information like version, fp precision, and preview thumbnail on hover

- +

diff --git a/StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageCardViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageCardViewModel.cs index a1b5571d..5c154c99 100644 --- a/StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageCardViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageCardViewModel.cs @@ -132,10 +132,16 @@ public partial class PackageCardViewModel : ProgressViewModel Text = $"Updating {Package.DisplayName}"; IsIndeterminate = true; + + var progressId = Guid.NewGuid(); + EventManager.Instance.OnProgressChanged(new ProgressItem(progressId, + Package.DisplayName, + new ProgressReport(0f, isIndeterminate: true, type: ProgressType.Update))); try { basePackage.InstallLocation = Package.FullPath!; + var progress = new Progress(progress => { var percent = Convert.ToInt32(progress.Percentage); @@ -145,6 +151,8 @@ public partial class PackageCardViewModel : ProgressViewModel Text = $"Updating {Package.DisplayName}"; EventManager.Instance.OnGlobalProgressChanged(percent); + EventManager.Instance.OnProgressChanged(new ProgressItem(progressId, + Package.DisplayName, progress)); }); var updateResult = await basePackage.Update(Package, progress); @@ -159,13 +167,19 @@ public partial class PackageCardViewModel : ProgressViewModel Package.UpdateAvailable = false; } IsUpdateAvailable = false; - InstalledVersion = Package.DisplayVersion ?? "Unknown"; + + EventManager.Instance.OnProgressChanged(new ProgressItem(progressId, + Package.DisplayName, + new ProgressReport(1f, "Update complete", type: ProgressType.Update))); } catch (Exception e) { logger.Error(e, "Error Updating Package ({PackageName})", basePackage.Name); notificationService.ShowPersistent($"Error Updating {Package.DisplayName}", e.Message, NotificationType.Error); + EventManager.Instance.OnProgressChanged(new ProgressItem(progressId, + Package.DisplayName, + new ProgressReport(0f, "Update failed", type: ProgressType.Update), Failed: true)); } finally { diff --git a/StabilityMatrix.Avalonia/ViewModels/ProgressItemViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/ProgressItemViewModel.cs index 9a450249..ceb7a2de 100644 --- a/StabilityMatrix.Avalonia/ViewModels/ProgressItemViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/ProgressItemViewModel.cs @@ -45,6 +45,8 @@ public partial class ProgressItemViewModel : ViewModelBase return Failed ? "Download Failed" : "Downloading..."; case ProgressType.Extract: return Failed ? "Extraction Failed" : "Extracting..."; + case ProgressType.Update: + return Failed ? "Update Failed" : "Updating..."; } if (Failed) diff --git a/StabilityMatrix.Avalonia/Views/ProgressManagerPage.axaml b/StabilityMatrix.Avalonia/Views/ProgressManagerPage.axaml index 06094bd4..f45ab5d3 100644 --- a/StabilityMatrix.Avalonia/Views/ProgressManagerPage.axaml +++ b/StabilityMatrix.Avalonia/Views/ProgressManagerPage.axaml @@ -39,6 +39,7 @@ @@ -50,10 +51,18 @@ - + + + + + + diff --git a/StabilityMatrix.Core/Database/LiteDbContext.cs b/StabilityMatrix.Core/Database/LiteDbContext.cs index c656d207..0e187e84 100644 --- a/StabilityMatrix.Core/Database/LiteDbContext.cs +++ b/StabilityMatrix.Core/Database/LiteDbContext.cs @@ -115,7 +115,19 @@ public class LiteDbContext : ILiteDbContext public void Dispose() { - database?.Dispose(); + if (database is not null) + { + try + { + database.Dispose(); + } + catch (ObjectDisposedException) + { + } + + database = null; + } + GC.SuppressFinalize(this); } } diff --git a/StabilityMatrix.Core/Models/Packages/A3WebUI.cs b/StabilityMatrix.Core/Models/Packages/A3WebUI.cs index 35976242..b9ac4540 100644 --- a/StabilityMatrix.Core/Models/Packages/A3WebUI.cs +++ b/StabilityMatrix.Core/Models/Packages/A3WebUI.cs @@ -193,23 +193,4 @@ public class A3WebUI : BaseGitPackage VenvRunner.RunDetached(args.TrimEnd(), HandleConsoleOutput, OnExit); } - - public override Task SetupModelFolders(DirectoryPath installDirectory) - { - StabilityMatrix.Core.Helper.SharedFolders - .SetupLinks(SharedFolders, SettingsManager.ModelsDirectory, installDirectory); - return Task.CompletedTask; - } - - public override async Task UpdateModelFolders(DirectoryPath installDirectory) - { - await StabilityMatrix.Core.Helper.SharedFolders.UpdateLinksForPackage(this, - SettingsManager.ModelsDirectory, installDirectory).ConfigureAwait(false); - } - - public override Task RemoveModelFolderLinks(DirectoryPath installDirectory) - { - StabilityMatrix.Core.Helper.SharedFolders.RemoveLinksForPackage(this, installDirectory); - return Task.CompletedTask; - } } diff --git a/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs b/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs index 2c47f0e4..6dddc6ef 100644 --- a/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs +++ b/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs @@ -5,6 +5,7 @@ using Octokit; using StabilityMatrix.Core.Helper; using StabilityMatrix.Core.Helper.Cache; using StabilityMatrix.Core.Models.Database; +using StabilityMatrix.Core.Models.FileInterfaces; using StabilityMatrix.Core.Models.Progress; using StabilityMatrix.Core.Python; using StabilityMatrix.Core.Services; @@ -265,6 +266,34 @@ public abstract class BaseGitPackage : BasePackage return latestCommit.Sha; } + public override Task SetupModelFolders(DirectoryPath installDirectory) + { + if (SharedFolders is { } folders) + { + StabilityMatrix.Core.Helper.SharedFolders + .SetupLinks(folders, SettingsManager.ModelsDirectory, installDirectory); + } + return Task.CompletedTask; + } + + public override async Task UpdateModelFolders(DirectoryPath installDirectory) + { + if (SharedFolders is not null) + { + await StabilityMatrix.Core.Helper.SharedFolders.UpdateLinksForPackage(this, + SettingsManager.ModelsDirectory, installDirectory).ConfigureAwait(false); + } + } + + public override Task RemoveModelFolderLinks(DirectoryPath installDirectory) + { + if (SharedFolders is not null) + { + StabilityMatrix.Core.Helper.SharedFolders.RemoveLinksForPackage(this, installDirectory); + } + return Task.CompletedTask; + } + // Send input to the running process. public virtual void SendInput(string input) { diff --git a/StabilityMatrix.Core/Models/Packages/InvokeAI.cs b/StabilityMatrix.Core/Models/Packages/InvokeAI.cs index 47c1df15..7ac7592a 100644 --- a/StabilityMatrix.Core/Models/Packages/InvokeAI.cs +++ b/StabilityMatrix.Core/Models/Packages/InvokeAI.cs @@ -327,25 +327,6 @@ public class InvokeAI : BaseGitPackage } } - public override Task SetupModelFolders(DirectoryPath installDirectory) - { - StabilityMatrix.Core.Helper.SharedFolders - .SetupLinks(SharedFolders, SettingsManager.ModelsDirectory, installDirectory); - return Task.CompletedTask; - } - - public override async Task UpdateModelFolders(DirectoryPath installDirectory) - { - await StabilityMatrix.Core.Helper.SharedFolders.UpdateLinksForPackage(this, - SettingsManager.ModelsDirectory, installDirectory).ConfigureAwait(false); - } - - public override Task RemoveModelFolderLinks(DirectoryPath installDirectory) - { - StabilityMatrix.Core.Helper.SharedFolders.RemoveLinksForPackage(this, installDirectory); - return Task.CompletedTask; - } - private Dictionary GetEnvVars(DirectoryPath installPath) { // Set additional required environment variables diff --git a/StabilityMatrix.Core/Models/Packages/VladAutomatic.cs b/StabilityMatrix.Core/Models/Packages/VladAutomatic.cs index 42e5ee70..bcf940a2 100644 --- a/StabilityMatrix.Core/Models/Packages/VladAutomatic.cs +++ b/StabilityMatrix.Core/Models/Packages/VladAutomatic.cs @@ -245,61 +245,6 @@ public class VladAutomatic : BaseGitPackage VenvRunner.RunDetached(args.TrimEnd(), HandleConsoleOutput, HandleExit); } - public override Task SetupModelFolders(DirectoryPath installDirectory) - { - var configJsonPath = installDirectory + "config.json"; - var exists = File.Exists(configJsonPath); - JsonObject? configRoot; - if (exists) - { - var configJson = File.ReadAllText(configJsonPath); - try - { - configRoot = JsonSerializer.Deserialize(configJson) ?? new JsonObject(); - } - catch (JsonException) - { - configRoot = new JsonObject(); - } - } - else - { - configRoot = new JsonObject(); - } - - configRoot["ckpt_dir"] = Path.Combine(SettingsManager.ModelsDirectory, "StableDiffusion"); - configRoot["diffusers_dir"] = Path.Combine(SettingsManager.ModelsDirectory, "Diffusers"); - configRoot["vae_dir"] = Path.Combine(SettingsManager.ModelsDirectory, "VAE"); - configRoot["lora_dir"] = Path.Combine(SettingsManager.ModelsDirectory, "Lora"); - configRoot["lyco_dir"] = Path.Combine(SettingsManager.ModelsDirectory, "LyCORIS"); - configRoot["embeddings_dir"] = Path.Combine(SettingsManager.ModelsDirectory, "TextualInversion"); - configRoot["hypernetwork_dir"] = Path.Combine(SettingsManager.ModelsDirectory, "Hypernetwork"); - configRoot["codeformer_models_path"] = Path.Combine(SettingsManager.ModelsDirectory, "Codeformer"); - configRoot["gfpgan_models_path"] = Path.Combine(SettingsManager.ModelsDirectory, "GFPGAN"); - configRoot["bsrgan_models_path"] = Path.Combine(SettingsManager.ModelsDirectory, "BSRGAN"); - configRoot["esrgan_models_path"] = Path.Combine(SettingsManager.ModelsDirectory, "ESRGAN"); - configRoot["realesrgan_models_path"] = Path.Combine(SettingsManager.ModelsDirectory, "RealESRGAN"); - configRoot["scunet_models_path"] = Path.Combine(SettingsManager.ModelsDirectory, "ScuNET"); - configRoot["swinir_models_path"] = Path.Combine(SettingsManager.ModelsDirectory, "SwinIR"); - configRoot["ldsr_models_path"] = Path.Combine(SettingsManager.ModelsDirectory, "LDSR"); - configRoot["clip_models_path"] = Path.Combine(SettingsManager.ModelsDirectory, "CLIP"); - configRoot["control_net_models_path"] = Path.Combine(SettingsManager.ModelsDirectory, "ControlNet"); - - var configJsonStr = JsonSerializer.Serialize(configRoot, new JsonSerializerOptions - { - WriteIndented = true - }); - File.WriteAllText(configJsonPath, configJsonStr); - - return Task.CompletedTask; - } - - public override Task UpdateModelFolders(DirectoryPath installDirectory) => - SetupModelFolders(installDirectory); - - public override Task RemoveModelFolderLinks(DirectoryPath installDirectory) => - Task.CompletedTask; - public override async Task Update(InstalledPackage installedPackage, IProgress? progress = null, bool includePrerelease = false) { diff --git a/StabilityMatrix.Core/Models/Packages/VoltaML.cs b/StabilityMatrix.Core/Models/Packages/VoltaML.cs index c566bd01..c221a342 100644 --- a/StabilityMatrix.Core/Models/Packages/VoltaML.cs +++ b/StabilityMatrix.Core/Models/Packages/VoltaML.cs @@ -178,23 +178,4 @@ public class VoltaML : BaseGitPackage VenvRunner.RunDetached(args.TrimEnd(), HandleConsoleOutput, OnExit); } - - public override Task SetupModelFolders(DirectoryPath installDirectory) - { - StabilityMatrix.Core.Helper.SharedFolders.SetupLinks(SharedFolders, - SettingsManager.ModelsDirectory, installDirectory); - return Task.CompletedTask; - } - - public override async Task UpdateModelFolders(DirectoryPath installDirectory) - { - await StabilityMatrix.Core.Helper.SharedFolders.UpdateLinksForPackage(this, - SettingsManager.ModelsDirectory, installDirectory).ConfigureAwait(false); - } - - public override Task RemoveModelFolderLinks(DirectoryPath installDirectory) - { - StabilityMatrix.Core.Helper.SharedFolders.RemoveLinksForPackage(this, installDirectory); - return Task.CompletedTask; - } } diff --git a/StabilityMatrix.Core/Models/Progress/ProgressType.cs b/StabilityMatrix.Core/Models/Progress/ProgressType.cs index 5d92e975..7b934e44 100644 --- a/StabilityMatrix.Core/Models/Progress/ProgressType.cs +++ b/StabilityMatrix.Core/Models/Progress/ProgressType.cs @@ -5,4 +5,5 @@ public enum ProgressType Generic, Download, Extract, + Update, }