diff --git a/CHANGELOG.md b/CHANGELOG.md
index e70bc12bb..a14178d4e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,24 @@ 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.10.1
+### Added
+- Added SVD Shared Model & Output Folders for Forge (fixes [#580](https://github.com/LykosAI/StabilityMatrix/issues/580))
+### Changed
+- Improved error message when logging in with a Lykos account fails due to incorrect email or password
+- Model Browser & Workflow Browser now auto-load when first navigating to those pages
+- Removed update confirmation dialog, instead showing the new version in the update button tooltip
+### Fixed
+- Fixed package launch not working when environment variable `SETUPTOOLS_USE_DISTUTILS` is set due to conflict with a default environment variable. User environment variables will now correctly override any default environment variables.
+- Fixed "No refresh token found" error when failing to login with Lykos account in some cases
+- Fixed blank entries appearing in the Categories dropdown on the Checkpoints page
+- Fixed crash when loading invalid connected model info files
+- Fixed [#585](https://github.com/LykosAI/StabilityMatrix/issues/585) - Crash when drag & drop source and destination are the same
+- Fixed [#584](https://github.com/LykosAI/StabilityMatrix/issues/584) - `--launch-package` argument not working
+- Fixed [#581](https://github.com/LykosAI/StabilityMatrix/issues/581) - Inference teaching tip showing more often than it should
+- Fixed [#578](https://github.com/LykosAI/StabilityMatrix/issues/578) - "python setup.py egg_info did not run successfully" failure when installing Auto1111 or SDWebUI Forge
+- Fixed [#574](https://github.com/LykosAI/StabilityMatrix/issues/574) - local images not showing on macOS or Linux
+
## v2.10.0
### Added
- Added Reference-Only mode for Inference ControlNet, used for guiding the sampler with an image without a pretrained model. Part of the latent and attention layers will be connected to the reference image, similar to Image to Image or Inpainting.
diff --git a/StabilityMatrix.Avalonia/Controls/Inference/ImageFolderCard.axaml b/StabilityMatrix.Avalonia/Controls/Inference/ImageFolderCard.axaml
index b34b8b42b..5609a5f71 100644
--- a/StabilityMatrix.Avalonia/Controls/Inference/ImageFolderCard.axaml
+++ b/StabilityMatrix.Avalonia/Controls/Inference/ImageFolderCard.axaml
@@ -11,6 +11,7 @@
xmlns:scroll="clr-namespace:StabilityMatrix.Avalonia.Controls.Scroll"
xmlns:labs="clr-namespace:Avalonia.Labs.Controls;assembly=Avalonia.Labs.Controls"
xmlns:vendorLabs="clr-namespace:StabilityMatrix.Avalonia.Controls.VendorLabs"
+ xmlns:converters="clr-namespace:StabilityMatrix.Avalonia.Converters"
x:DataType="vmInference:ImageFolderCardViewModel">
@@ -20,6 +21,8 @@
+
+
@@ -200,7 +203,7 @@
+ IsOpen="{Binding IsHelpButtonTeachingTipOpen, Mode=TwoWay}"/>
new Uri(str),
string str => new Uri("file://" + str),
IFormattable formattable => new Uri("file://" + formattable.ToString(null, culture)),
_ => null
diff --git a/StabilityMatrix.Avalonia/Services/INavigationService.cs b/StabilityMatrix.Avalonia/Services/INavigationService.cs
index 68f7f261f..690966da4 100644
--- a/StabilityMatrix.Avalonia/Services/INavigationService.cs
+++ b/StabilityMatrix.Avalonia/Services/INavigationService.cs
@@ -39,4 +39,5 @@ void NavigateTo(
bool GoBack();
bool CanGoBack { get; }
+ object? CurrentPageDataContext { get; }
}
diff --git a/StabilityMatrix.Avalonia/Services/NavigationService.cs b/StabilityMatrix.Avalonia/Services/NavigationService.cs
index 8778f7ca4..9e6ac8015 100644
--- a/StabilityMatrix.Avalonia/Services/NavigationService.cs
+++ b/StabilityMatrix.Avalonia/Services/NavigationService.cs
@@ -1,5 +1,6 @@
using System;
using System.Linq;
+using Avalonia.Controls;
using FluentAvalonia.UI.Controls;
using FluentAvalonia.UI.Media.Animation;
using FluentAvalonia.UI.Navigation;
@@ -190,4 +191,6 @@ public bool GoBack()
}
public bool CanGoBack => _frame?.CanGoBack ?? false;
+
+ public object? CurrentPageDataContext => (_frame?.Content as Control)?.DataContext;
}
diff --git a/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/CivitAiBrowserViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/CivitAiBrowserViewModel.cs
index ebf5401af..26364b0db 100644
--- a/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/CivitAiBrowserViewModel.cs
+++ b/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/CivitAiBrowserViewModel.cs
@@ -177,6 +177,8 @@ public override void OnLoaded()
model => model.ShowNsfw,
settings => settings.ModelBrowserNsfwEnabled
);
+
+ SearchModelsCommand.ExecuteAsync(false);
}
///
diff --git a/StabilityMatrix.Avalonia/ViewModels/CheckpointManager/CheckpointFile.cs b/StabilityMatrix.Avalonia/ViewModels/CheckpointManager/CheckpointFile.cs
index baebb0fde..15eb4f5dc 100644
--- a/StabilityMatrix.Avalonia/ViewModels/CheckpointManager/CheckpointFile.cs
+++ b/StabilityMatrix.Avalonia/ViewModels/CheckpointManager/CheckpointFile.cs
@@ -3,6 +3,7 @@
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
+using System.Text.Json;
using System.Threading.Tasks;
using Avalonia.Data;
using CommunityToolkit.Mvvm.ComponentModel;
@@ -10,7 +11,6 @@
using FluentAvalonia.UI.Controls;
using Microsoft.Extensions.DependencyInjection;
using NLog;
-using StabilityMatrix.Avalonia.Languages;
using StabilityMatrix.Avalonia.ViewModels.Base;
using StabilityMatrix.Core.Attributes;
using StabilityMatrix.Core.Extensions;
@@ -333,8 +333,15 @@ public static IEnumerable FromDirectoryIndex(
if (File.Exists(jsonPath))
{
var json = File.ReadAllText(jsonPath);
- var connectedModelInfo = ConnectedModelInfo.FromJson(json);
- checkpointFile.ConnectedModel = connectedModelInfo;
+ try
+ {
+ var connectedModelInfo = ConnectedModelInfo.FromJson(json);
+ checkpointFile.ConnectedModel = connectedModelInfo;
+ }
+ catch (JsonException)
+ {
+ checkpointFile.ConnectedModel = null;
+ }
}
checkpointFile.PreviewImagePath = SupportedImageExtensions
diff --git a/StabilityMatrix.Avalonia/ViewModels/CheckpointManager/CheckpointFolder.cs b/StabilityMatrix.Avalonia/ViewModels/CheckpointManager/CheckpointFolder.cs
index 394081292..5f23e3fc4 100644
--- a/StabilityMatrix.Avalonia/ViewModels/CheckpointManager/CheckpointFolder.cs
+++ b/StabilityMatrix.Avalonia/ViewModels/CheckpointManager/CheckpointFolder.cs
@@ -92,7 +92,8 @@ public partial class CheckpointFolder : ViewModelBase
public string TitleWithFilesCount =>
CheckpointFiles.Any() || SubFolders.Any(f => f.CheckpointFiles.Any())
- ? $"{FolderType.GetDescription() ?? FolderType.GetStringValue()} ({CheckpointFiles.Count + SubFolders.Sum(folder => folder.CheckpointFiles.Count)})"
+ ? $"{FolderType.GetDescription() ?? (string.IsNullOrWhiteSpace(FolderType.GetStringValue()) ? Path.GetFileName(DirectoryPath) : FolderType.GetStringValue())} "
+ + $"({CheckpointFiles.Count + SubFolders.Sum(folder => folder.CheckpointFiles.Count)})"
: FolderType.GetDescription() ?? FolderType.GetStringValue();
public ProgressViewModel Progress { get; } = new();
@@ -447,6 +448,22 @@ public async Task ImportFilesAsync(IEnumerable files, bool convertToConn
Progress.Value = 0;
var copyPaths = files.ToDictionary(k => k, v => Path.Combine(DirectoryPath, Path.GetFileName(v)));
+ // remove files that are already in the folder
+ foreach (var (source, destination) in copyPaths)
+ {
+ if (source == destination)
+ {
+ copyPaths.Remove(source);
+ }
+ }
+
+ if (copyPaths.Count == 0)
+ {
+ Progress.Text = "Import complete";
+ Progress.Value = 100;
+ return;
+ }
+
var progress = new Progress(report =>
{
Progress.IsIndeterminate = false;
diff --git a/StabilityMatrix.Avalonia/ViewModels/Dialogs/LykosLoginViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/Dialogs/LykosLoginViewModel.cs
index 471d052b7..7dd14a8b2 100644
--- a/StabilityMatrix.Avalonia/ViewModels/Dialogs/LykosLoginViewModel.cs
+++ b/StabilityMatrix.Avalonia/ViewModels/Dialogs/LykosLoginViewModel.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
+using System.Net;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
@@ -90,7 +91,15 @@ private async Task LoginAsync()
}
catch (ApiException e)
{
- LoginError = new AppException("Failed to login", $"{e.StatusCode} - {e.Message}");
+ LoginError = e.StatusCode switch
+ {
+ HttpStatusCode.Unauthorized
+ => new AppException(
+ "Incorrect email or password",
+ "Please try again or reset your password"
+ ),
+ _ => new AppException("Failed to login", $"{e.StatusCode} - {e.Message}")
+ };
}
}
diff --git a/StabilityMatrix.Avalonia/ViewModels/OpenArtBrowserViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/OpenArtBrowserViewModel.cs
index de438ecc6..cc13e869a 100644
--- a/StabilityMatrix.Avalonia/ViewModels/OpenArtBrowserViewModel.cs
+++ b/StabilityMatrix.Avalonia/ViewModels/OpenArtBrowserViewModel.cs
@@ -12,7 +12,6 @@
using FluentAvalonia.UI.Controls;
using Refit;
using StabilityMatrix.Avalonia.Controls;
-using StabilityMatrix.Avalonia.Languages;
using StabilityMatrix.Avalonia.Models;
using StabilityMatrix.Avalonia.Services;
using StabilityMatrix.Avalonia.ViewModels.Base;
@@ -36,8 +35,7 @@ public partial class OpenArtBrowserViewModel(
IOpenArtApi openArtApi,
INotificationService notificationService,
ISettingsManager settingsManager,
- IPackageFactory packageFactory,
- ServiceManager vmFactory
+ IPackageFactory packageFactory
) : TabViewModelBase, IInfinitelyScroll
{
private const int PageSize = 20;
@@ -90,6 +88,7 @@ protected override void OnInitialLoaded()
{
searchResultsCache.Connect().DeferUntilLoaded().Bind(SearchResults).Subscribe();
SelectedSortMode = AllSortModes.First();
+ DoSearch().SafeFireAndForget();
}
[RelayCommand]
diff --git a/StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageCardViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageCardViewModel.cs
index 71d624ecb..7d38ca8de 100644
--- a/StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageCardViewModel.cs
+++ b/StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageCardViewModel.cs
@@ -95,6 +95,9 @@ RunningPackageService runningPackageService
[ObservableProperty]
private bool showWebUiButton;
+ [ObservableProperty]
+ private DownloadPackageVersionOptions? updateVersion;
+
private void RunningPackagesOnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
if (runningPackageService.RunningPackages.Select(x => x.Value) is not { } runningPackages)
@@ -196,6 +199,10 @@ and not UnknownPackage
}
IsUpdateAvailable = await HasUpdate();
+ if (IsUpdateAvailable)
+ {
+ UpdateVersion = await basePackage.GetUpdate(currentPackage);
+ }
if (
Package != null
@@ -426,21 +433,6 @@ public async Task Update()
versionOptions.CommitHash = latest.Sha;
}
- var confirmationDialog = new BetterContentDialog
- {
- Title = Resources.Label_AreYouSure,
- Content =
- $"{Package.DisplayName} will be updated to the latest version ({versionOptions.GetReadableVersionString()})",
- PrimaryButtonText = Resources.Action_Continue,
- SecondaryButtonText = Resources.Action_Cancel,
- DefaultButton = ContentDialogButton.Primary,
- IsSecondaryButtonEnabled = true,
- };
-
- var dialogResult = await confirmationDialog.ShowAsync();
- if (dialogResult != ContentDialogResult.Primary)
- return;
-
var updatePackageStep = new UpdatePackageStep(
settingsManager,
Package,
@@ -672,6 +664,7 @@ private async Task HasUpdate()
try
{
var hasUpdate = await basePackage.CheckForUpdates(Package);
+ UpdateVersion = await basePackage.GetUpdate(Package);
await using (settingsManager.BeginTransaction())
{
diff --git a/StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageInstallDetailViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageInstallDetailViewModel.cs
index 6c24efc2f..5766a8a84 100644
--- a/StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageInstallDetailViewModel.cs
+++ b/StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageInstallDetailViewModel.cs
@@ -283,6 +283,13 @@ private async Task Install()
if (!runner.Failed)
{
+ if (ReferenceEquals(this, packageNavigationService.CurrentPageDataContext))
+ {
+ packageNavigationService.GoBack();
+ packageNavigationService.GoBack();
+ await Task.Delay(100);
+ }
+
EventManager.Instance.OnInstalledPackagesChanged();
}
}
diff --git a/StabilityMatrix.Avalonia/ViewModels/PackageManagerViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/PackageManagerViewModel.cs
index 9d59df054..faf3e63f6 100644
--- a/StabilityMatrix.Avalonia/ViewModels/PackageManagerViewModel.cs
+++ b/StabilityMatrix.Avalonia/ViewModels/PackageManagerViewModel.cs
@@ -42,6 +42,7 @@ public partial class PackageManagerViewModel : PageViewModelBase
private readonly INotificationService notificationService;
private readonly INavigationService packageNavigationService;
private readonly ILogger logger;
+ private readonly RunningPackageService runningPackageService;
public override string Title => Resources.Label_Packages;
public override IconSource IconSource => new SymbolIconSource { Symbol = Symbol.Box, IsFilled = true };
@@ -69,7 +70,8 @@ public PackageManagerViewModel(
ServiceManager dialogFactory,
INotificationService notificationService,
INavigationService packageNavigationService,
- ILogger logger
+ ILogger logger,
+ RunningPackageService runningPackageService
)
{
this.settingsManager = settingsManager;
@@ -77,6 +79,7 @@ ILogger logger
this.notificationService = notificationService;
this.packageNavigationService = packageNavigationService;
this.logger = logger;
+ this.runningPackageService = runningPackageService;
EventManager.Instance.InstalledPackagesChanged += OnInstalledPackagesChanged;
EventManager.Instance.OneClickInstallFinished += OnOneClickInstallFinished;
@@ -118,15 +121,39 @@ public void SetUnknownPackages(IEnumerable packages)
unknownInstalledPackages.Edit(s => s.Load(packages));
}
+ protected override async Task OnInitialLoadedAsync()
+ {
+ if (string.IsNullOrWhiteSpace(Program.Args.LaunchPackageName))
+ {
+ await base.OnInitialLoadedAsync();
+ return;
+ }
+
+ await LoadPackages();
+
+ var package = Packages.FirstOrDefault(x => x.DisplayName == Program.Args.LaunchPackageName);
+ if (package is not null)
+ {
+ await runningPackageService.StartPackage(package);
+ return;
+ }
+
+ package = Packages.FirstOrDefault(x => x.Id.ToString() == Program.Args.LaunchPackageName);
+ if (package is null)
+ {
+ await base.OnInitialLoadedAsync();
+ return;
+ }
+
+ await runningPackageService.StartPackage(package);
+ }
+
public override async Task OnLoadedAsync()
{
if (Design.IsDesignMode || !settingsManager.IsLibraryDirSet)
return;
- installedPackages.EditDiff(settingsManager.Settings.InstalledPackages, InstalledPackage.Comparer);
-
- var currentUnknown = await Task.Run(IndexUnknownPackages);
- unknownInstalledPackages.Edit(s => s.Load(currentUnknown));
+ await LoadPackages();
timer.Start();
}
@@ -142,6 +169,14 @@ public void ShowInstallDialog(BasePackage? selectedPackage = null)
NavigateToSubPage(typeof(PackageInstallBrowserViewModel));
}
+ private async Task LoadPackages()
+ {
+ installedPackages.EditDiff(settingsManager.Settings.InstalledPackages, InstalledPackage.Comparer);
+
+ var currentUnknown = await Task.Run(IndexUnknownPackages);
+ unknownInstalledPackages.Edit(s => s.Load(currentUnknown));
+ }
+
private async Task CheckPackagesForUpdates()
{
foreach (var package in PackageCards)
diff --git a/StabilityMatrix.Avalonia/Views/CheckpointsPage.axaml b/StabilityMatrix.Avalonia/Views/CheckpointsPage.axaml
index facb12987..61c0afd45 100644
--- a/StabilityMatrix.Avalonia/Views/CheckpointsPage.axaml
+++ b/StabilityMatrix.Avalonia/Views/CheckpointsPage.axaml
@@ -31,6 +31,7 @@
x:Key="TextDropShadowEffect" />
+
@@ -143,7 +144,7 @@
+
+
+
+
+
@@ -177,7 +183,7 @@
ImageHeight="{Binding $parent[ItemsRepeater].((vm:OutputsPageViewModel)DataContext).ImageSize.Height}"
ImageWidth="{Binding $parent[ItemsRepeater].((vm:OutputsPageViewModel)DataContext).ImageSize.Width}"
IsSelected="{Binding IsSelected}"
- Source="{Binding ImageFile.AbsolutePath}">
+ Source="{Binding ImageFile.AbsolutePath, Converter={StaticResource FileUriConverter}}">
+
+
+
+
+
+
diff --git a/StabilityMatrix.Avalonia/Views/Settings/MainSettingsPage.axaml b/StabilityMatrix.Avalonia/Views/Settings/MainSettingsPage.axaml
index 5fb2d8a40..15eea9f1a 100644
--- a/StabilityMatrix.Avalonia/Views/Settings/MainSettingsPage.axaml
+++ b/StabilityMatrix.Avalonia/Views/Settings/MainSettingsPage.axaml
@@ -82,19 +82,6 @@
Symbol="Alert" />
-
-
-
-
-
-
-
-
@@ -215,7 +202,7 @@
-
+
+
+
+
+
+
+
+
+
+
+
(
r =>
r.StatusCode is HttpStatusCode.Unauthorized or HttpStatusCode.Forbidden
- && r.RequestMessage?.Headers.Authorization
- is { Scheme: "Bearer", Parameter: not null }
+ && r.RequestMessage?.Headers.Authorization is { Scheme: "Bearer", Parameter: { } param }
+ && !string.IsNullOrWhiteSpace(param)
)
.RetryAsync(
async (result, _) =>
@@ -35,9 +35,7 @@ await tokenProvider.GetAccessTokenAsync().ConfigureAwait(false)
"Refreshing access token for status ({StatusCode})",
result.Result.StatusCode
);
- var (newToken, _) = await tokenProvider
- .RefreshTokensAsync()
- .ConfigureAwait(false);
+ var (newToken, _) = await tokenProvider.RefreshTokensAsync().ConfigureAwait(false);
Logger.Info(
"Access token refreshed: {OldToken} -> {NewToken}",
@@ -46,10 +44,6 @@ await tokenProvider.GetAccessTokenAsync().ConfigureAwait(false)
);
}
);
-
- // InnerHandler must be left as null when using DI, but must be assigned a value when
- // using RestService.For
- // InnerHandler = new HttpClientHandler();
}
protected override Task SendAsync(
@@ -59,9 +53,17 @@ CancellationToken cancellationToken
{
return policy.ExecuteAsync(async () =>
{
- var accessToken = await tokenProvider.GetAccessTokenAsync().ConfigureAwait(false);
+ // Only add if Authorization is already set to Bearer and access token is not empty
+ // this allows some routes to not use the access token
+ if (request.Headers.Authorization is { Scheme: "Bearer" })
+ {
+ var accessToken = await tokenProvider.GetAccessTokenAsync().ConfigureAwait(false);
- request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
+ if (!string.IsNullOrWhiteSpace(accessToken))
+ {
+ request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
+ }
+ }
return await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
});
diff --git a/StabilityMatrix.Core/Models/DownloadPackageVersionOptions.cs b/StabilityMatrix.Core/Models/DownloadPackageVersionOptions.cs
index da41388a9..2be760307 100644
--- a/StabilityMatrix.Core/Models/DownloadPackageVersionOptions.cs
+++ b/StabilityMatrix.Core/Models/DownloadPackageVersionOptions.cs
@@ -10,4 +10,6 @@ public class DownloadPackageVersionOptions
public string GetReadableVersionString() =>
!string.IsNullOrWhiteSpace(VersionTag) ? VersionTag : $"{BranchName}@{CommitHash?[..7]}";
+
+ public string ReadableVersionString => GetReadableVersionString();
}
diff --git a/StabilityMatrix.Core/Models/Packages/A3WebUI.cs b/StabilityMatrix.Core/Models/Packages/A3WebUI.cs
index 9635cecc4..9e9b5b806 100644
--- a/StabilityMatrix.Core/Models/Packages/A3WebUI.cs
+++ b/StabilityMatrix.Core/Models/Packages/A3WebUI.cs
@@ -66,7 +66,8 @@ IPrerequisiteHelper prerequisiteHelper
[SharedFolderType.T2IAdapter] = new[] { "models/controlnet/T2IAdapter" },
[SharedFolderType.IpAdapter] = new[] { "models/controlnet/IpAdapter" },
[SharedFolderType.InvokeIpAdapters15] = new[] { "models/controlnet/DiffusersIpAdapters" },
- [SharedFolderType.InvokeIpAdaptersXl] = new[] { "models/controlnet/DiffusersIpAdaptersXL" }
+ [SharedFolderType.InvokeIpAdaptersXl] = new[] { "models/controlnet/DiffusersIpAdaptersXL" },
+ [SharedFolderType.SVD] = new[] { "models/svd" }
};
public override Dictionary>? SharedOutputFolders =>
@@ -77,7 +78,8 @@ IPrerequisiteHelper prerequisiteHelper
[SharedOutputType.Img2Img] = new[] { "output/img2img-images" },
[SharedOutputType.Text2Img] = new[] { "output/txt2img-images" },
[SharedOutputType.Img2ImgGrids] = new[] { "output/img2img-grids" },
- [SharedOutputType.Text2ImgGrids] = new[] { "output/txt2img-grids" }
+ [SharedOutputType.Text2ImgGrids] = new[] { "output/txt2img-grids" },
+ [SharedOutputType.SVD] = new[] { "output/svd" }
};
[SuppressMessage("ReSharper", "ArrangeObjectCreationWhenTypeNotEvident")]
@@ -204,6 +206,8 @@ public override async Task InstallPackage(
await using var venvRunner = new PyVenvRunner(venvPath);
venvRunner.WorkingDirectory = installLocation;
+ venvRunner.EnvironmentVariables = settingsManager.Settings.EnvironmentVariables;
+
await venvRunner.Setup(true, onConsoleOutput).ConfigureAwait(false);
await venvRunner.PipInstall("--upgrade pip wheel", onConsoleOutput).ConfigureAwait(false);
diff --git a/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs b/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs
index 86a103c58..e368790d4 100644
--- a/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs
+++ b/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs
@@ -345,6 +345,54 @@ await GetAllCommits(currentVersion.InstalledBranch!).ConfigureAwait(false)
}
}
+ public override async Task GetUpdate(InstalledPackage installedPackage)
+ {
+ var currentVersion = installedPackage.Version;
+ if (currentVersion is null or { InstalledReleaseVersion: null, InstalledBranch: null })
+ {
+ Logger.Warn(
+ "Could not check updates for package {Name}, version is invalid: {@currentVersion}",
+ Name,
+ currentVersion
+ );
+ return null;
+ }
+
+ var versionOptions = new DownloadPackageVersionOptions { IsLatest = true };
+
+ try
+ {
+ if (currentVersion.IsReleaseMode)
+ {
+ var latestVersion = await GetLatestVersion(currentVersion.IsPrerelease).ConfigureAwait(false);
+ versionOptions.IsPrerelease = latestVersion.IsPrerelease;
+ versionOptions.VersionTag = latestVersion.VersionTag;
+ return versionOptions;
+ }
+
+ var allCommits = (
+ await GetAllCommits(currentVersion.InstalledBranch!).ConfigureAwait(false)
+ )?.ToList();
+
+ if (allCommits == null || !allCommits.Any())
+ {
+ Logger.Warn("No commits found for {Package}", installedPackage.PackageName);
+ return null;
+ }
+ var latestCommitHash = allCommits.First().Sha;
+
+ versionOptions.CommitHash = latestCommitHash;
+ versionOptions.BranchName = currentVersion.InstalledBranch;
+
+ return versionOptions;
+ }
+ catch (ApiException e)
+ {
+ Logger.Warn(e, "Failed to check for package updates");
+ return null;
+ }
+ }
+
public override async Task Update(
InstalledPackage installedPackage,
TorchVersion torchVersion,
diff --git a/StabilityMatrix.Core/Models/Packages/BasePackage.cs b/StabilityMatrix.Core/Models/Packages/BasePackage.cs
index 368cf2bcb..a603c2a42 100644
--- a/StabilityMatrix.Core/Models/Packages/BasePackage.cs
+++ b/StabilityMatrix.Core/Models/Packages/BasePackage.cs
@@ -237,4 +237,6 @@ protected Task InstallCpuTorch(
onConsoleOutput
);
}
+
+ public abstract Task GetUpdate(InstalledPackage installedPackage);
}
diff --git a/StabilityMatrix.Core/Models/Packages/ComfyUI.cs b/StabilityMatrix.Core/Models/Packages/ComfyUI.cs
index c620182cd..61c10f96c 100644
--- a/StabilityMatrix.Core/Models/Packages/ComfyUI.cs
+++ b/StabilityMatrix.Core/Models/Packages/ComfyUI.cs
@@ -195,8 +195,9 @@ public override async Task InstallPackage(
// Setup venv
await using var venvRunner = new PyVenvRunner(Path.Combine(installLocation, "venv"));
venvRunner.WorkingDirectory = installLocation;
- await venvRunner.Setup(true, onConsoleOutput).ConfigureAwait(false);
+ venvRunner.EnvironmentVariables = settingsManager.Settings.EnvironmentVariables;
+ await venvRunner.Setup(true, onConsoleOutput).ConfigureAwait(false);
await venvRunner.PipInstall("--upgrade pip wheel", onConsoleOutput).ConfigureAwait(false);
progress?.Report(
@@ -245,6 +246,7 @@ await requirements.ReadAllTextAsync().ConfigureAwait(false),
excludePattern: "torch"
);
+ await venvRunner.PipUninstall("xformers", onConsoleOutput).ConfigureAwait(false);
await venvRunner.PipInstall(pipArgs, onConsoleOutput).ConfigureAwait(false);
progress?.Report(new ProgressReport(1, "Installed Package Requirements", isIndeterminate: false));
diff --git a/StabilityMatrix.Core/Models/Packages/Fooocus.cs b/StabilityMatrix.Core/Models/Packages/Fooocus.cs
index 2faaab4f7..fcaff9538 100644
--- a/StabilityMatrix.Core/Models/Packages/Fooocus.cs
+++ b/StabilityMatrix.Core/Models/Packages/Fooocus.cs
@@ -193,6 +193,7 @@ public override async Task InstallPackage(
)
{
var venvRunner = await SetupVenv(installLocation, forceRecreate: true).ConfigureAwait(false);
+ venvRunner.EnvironmentVariables = settingsManager.Settings.EnvironmentVariables;
progress?.Report(new ProgressReport(-1f, "Installing requirements...", isIndeterminate: true));
diff --git a/StabilityMatrix.Core/Models/Packages/FooocusMre.cs b/StabilityMatrix.Core/Models/Packages/FooocusMre.cs
index 82497f0f5..4ecaea250 100644
--- a/StabilityMatrix.Core/Models/Packages/FooocusMre.cs
+++ b/StabilityMatrix.Core/Models/Packages/FooocusMre.cs
@@ -111,6 +111,7 @@ public override async Task InstallPackage(
)
{
var venvRunner = await SetupVenv(installLocation, forceRecreate: true).ConfigureAwait(false);
+ venvRunner.EnvironmentVariables = settingsManager.Settings.EnvironmentVariables;
progress?.Report(new ProgressReport(-1f, "Installing torch...", isIndeterminate: true));
diff --git a/StabilityMatrix.Core/Models/Packages/KohyaSs.cs b/StabilityMatrix.Core/Models/Packages/KohyaSs.cs
index 594f95ec4..701da6992 100644
--- a/StabilityMatrix.Core/Models/Packages/KohyaSs.cs
+++ b/StabilityMatrix.Core/Models/Packages/KohyaSs.cs
@@ -126,9 +126,12 @@ await PrerequisiteHelper
.ConfigureAwait(false);
progress?.Report(new ProgressReport(-1f, "Setting up venv", isIndeterminate: true));
+
// Setup venv
await using var venvRunner = new PyVenvRunner(Path.Combine(installLocation, "venv"));
venvRunner.WorkingDirectory = installLocation;
+ venvRunner.EnvironmentVariables = settingsManager.Settings.EnvironmentVariables;
+
await venvRunner.Setup(true, onConsoleOutput).ConfigureAwait(false);
// Extra dep needed before running setup since v23.0.x
diff --git a/StabilityMatrix.Core/Models/Packages/OneTrainer.cs b/StabilityMatrix.Core/Models/Packages/OneTrainer.cs
index d4a92c342..4a6887e65 100644
--- a/StabilityMatrix.Core/Models/Packages/OneTrainer.cs
+++ b/StabilityMatrix.Core/Models/Packages/OneTrainer.cs
@@ -57,6 +57,8 @@ public override async Task InstallPackage(
await using var venvRunner = new PyVenvRunner(Path.Combine(installLocation, "venv"));
venvRunner.WorkingDirectory = installLocation;
+ venvRunner.EnvironmentVariables = settingsManager.Settings.EnvironmentVariables;
+
await venvRunner.Setup(true, onConsoleOutput).ConfigureAwait(false);
progress?.Report(new ProgressReport(-1f, "Installing requirements", isIndeterminate: true));
diff --git a/StabilityMatrix.Core/Models/Packages/RuinedFooocus.cs b/StabilityMatrix.Core/Models/Packages/RuinedFooocus.cs
index 96dc5d65b..194b431e5 100644
--- a/StabilityMatrix.Core/Models/Packages/RuinedFooocus.cs
+++ b/StabilityMatrix.Core/Models/Packages/RuinedFooocus.cs
@@ -116,6 +116,7 @@ public override async Task InstallPackage(
if (torchVersion == TorchVersion.Cuda)
{
var venvRunner = await SetupVenv(installLocation, forceRecreate: true).ConfigureAwait(false);
+ venvRunner.EnvironmentVariables = settingsManager.Settings.EnvironmentVariables;
progress?.Report(new ProgressReport(-1f, "Installing requirements...", isIndeterminate: true));
diff --git a/StabilityMatrix.Core/Models/Packages/SDWebForge.cs b/StabilityMatrix.Core/Models/Packages/SDWebForge.cs
index f64a41976..e3be760f4 100644
--- a/StabilityMatrix.Core/Models/Packages/SDWebForge.cs
+++ b/StabilityMatrix.Core/Models/Packages/SDWebForge.cs
@@ -41,17 +41,6 @@ IPrerequisiteHelper prerequisiteHelper
public override string OutputFolderName => "output";
public override PackageDifficulty InstallerSortOrder => PackageDifficulty.ReallyRecommended;
- public override Dictionary>? SharedOutputFolders =>
- new()
- {
- [SharedOutputType.Extras] = new[] { "output/extras-images" },
- [SharedOutputType.Saved] = new[] { "log/images" },
- [SharedOutputType.Img2Img] = new[] { "output/img2img-images" },
- [SharedOutputType.Text2Img] = new[] { "output/txt2img-images" },
- [SharedOutputType.Img2ImgGrids] = new[] { "output/img2img-grids" },
- [SharedOutputType.Text2ImgGrids] = new[] { "output/txt2img-grids" }
- };
-
public override List LaunchOptions =>
[
new LaunchOptionDefinition
@@ -142,6 +131,8 @@ public override async Task InstallPackage(
await using var venvRunner = new PyVenvRunner(venvPath);
venvRunner.WorkingDirectory = installLocation;
+ venvRunner.EnvironmentVariables = settingsManager.Settings.EnvironmentVariables;
+
await venvRunner.Setup(true, onConsoleOutput).ConfigureAwait(false);
await venvRunner.PipInstall("--upgrade pip wheel", onConsoleOutput).ConfigureAwait(false);
diff --git a/StabilityMatrix.Core/Models/Packages/StableDiffusionDirectMl.cs b/StabilityMatrix.Core/Models/Packages/StableDiffusionDirectMl.cs
index c35b37b88..037725a86 100644
--- a/StabilityMatrix.Core/Models/Packages/StableDiffusionDirectMl.cs
+++ b/StabilityMatrix.Core/Models/Packages/StableDiffusionDirectMl.cs
@@ -76,6 +76,8 @@ public override async Task InstallPackage(
// Setup venv
await using var venvRunner = new PyVenvRunner(Path.Combine(installLocation, "venv"));
venvRunner.WorkingDirectory = installLocation;
+ venvRunner.EnvironmentVariables = settingsManager.Settings.EnvironmentVariables;
+
await venvRunner.Setup(true, onConsoleOutput).ConfigureAwait(false);
switch (torchVersion)
diff --git a/StabilityMatrix.Core/Models/Packages/StableDiffusionUx.cs b/StabilityMatrix.Core/Models/Packages/StableDiffusionUx.cs
index 98f853505..5b5cacfac 100644
--- a/StabilityMatrix.Core/Models/Packages/StableDiffusionUx.cs
+++ b/StabilityMatrix.Core/Models/Packages/StableDiffusionUx.cs
@@ -190,6 +190,8 @@ public override async Task InstallPackage(
// Setup venv
await using var venvRunner = new PyVenvRunner(Path.Combine(installLocation, "venv"));
venvRunner.WorkingDirectory = installLocation;
+ venvRunner.EnvironmentVariables = settingsManager.Settings.EnvironmentVariables;
+
await venvRunner.Setup(true, onConsoleOutput).ConfigureAwait(false);
switch (torchVersion)
diff --git a/StabilityMatrix.Core/Models/Packages/UnknownPackage.cs b/StabilityMatrix.Core/Models/Packages/UnknownPackage.cs
index 89d021e0b..b1e523399 100644
--- a/StabilityMatrix.Core/Models/Packages/UnknownPackage.cs
+++ b/StabilityMatrix.Core/Models/Packages/UnknownPackage.cs
@@ -15,8 +15,7 @@ public class UnknownPackage : BasePackage
public override string GithubUrl => "";
public override string LicenseType => "AGPL-3.0";
- public override string LicenseUrl =>
- "https://github.com/LykosAI/StabilityMatrix/blob/main/LICENSE";
+ public override string LicenseUrl => "https://github.com/LykosAI/StabilityMatrix/blob/main/LICENSE";
public override string Blurb => "A dank interface for diffusion";
public override string LaunchCommand => "test";
@@ -140,20 +139,20 @@ public override Task> GetReleaseTags() =>
public override List LaunchOptions => new();
public override Dictionary>? SharedFolders { get; }
- public override Dictionary<
- SharedOutputType,
- IReadOnlyList
- >? SharedOutputFolders { get; }
+ public override Dictionary>? SharedOutputFolders { get; }
- public override Task GetLatestVersion(
- bool includePrerelease = false
- )
+ public override Task GetLatestVersion(bool includePrerelease = false)
{
throw new NotImplementedException();
}
public override string MainBranch { get; }
+ public override Task GetUpdate(InstalledPackage installedPackage)
+ {
+ return Task.FromResult(new DownloadPackageVersionOptions { IsLatest = true, VersionTag = "1.8.0" });
+ }
+
public override Task GetAllVersionOptions() =>
Task.FromResult(new PackageVersionOptions());
diff --git a/StabilityMatrix.Core/Models/Packages/VoltaML.cs b/StabilityMatrix.Core/Models/Packages/VoltaML.cs
index 95acb9700..dba66a526 100644
--- a/StabilityMatrix.Core/Models/Packages/VoltaML.cs
+++ b/StabilityMatrix.Core/Models/Packages/VoltaML.cs
@@ -21,12 +21,15 @@ IPrerequisiteHelper prerequisiteHelper
public override string DisplayName { get; set; } = "VoltaML";
public override string Author => "VoltaML";
public override string LicenseType => "GPL-3.0";
- public override string LicenseUrl => "https://github.com/VoltaML/voltaML-fast-stable-diffusion/blob/main/License";
+ public override string LicenseUrl =>
+ "https://github.com/VoltaML/voltaML-fast-stable-diffusion/blob/main/License";
public override string Blurb => "Fast Stable Diffusion with support for AITemplate";
public override string LaunchCommand => "main.py";
public override Uri PreviewImageUri =>
- new("https://github.com/LykosAI/StabilityMatrix/assets/13956642/d9a908ed-5665-41a5-a380-98458f4679a8");
+ new(
+ "https://github.com/LykosAI/StabilityMatrix/assets/13956642/d9a908ed-5665-41a5-a380-98458f4679a8"
+ );
public override PackageDifficulty InstallerSortOrder => PackageDifficulty.Simple;
@@ -155,6 +158,7 @@ public override async Task InstallPackage(
progress?.Report(new ProgressReport(-1, "Setting up venv", isIndeterminate: true));
await using var venvRunner = new PyVenvRunner(Path.Combine(installLocation, "venv"));
venvRunner.WorkingDirectory = installLocation;
+ venvRunner.EnvironmentVariables = settingsManager.Settings.EnvironmentVariables;
await venvRunner.Setup(true, onConsoleOutput).ConfigureAwait(false);
diff --git a/StabilityMatrix.Core/Models/Settings/Settings.cs b/StabilityMatrix.Core/Models/Settings/Settings.cs
index 01e22fd2f..ff65f1049 100644
--- a/StabilityMatrix.Core/Models/Settings/Settings.cs
+++ b/StabilityMatrix.Core/Models/Settings/Settings.cs
@@ -118,10 +118,22 @@ public InstalledPackage? PreferredWorkflowPackage
public Dictionary? UserEnvironmentVariables { get; set; }
[JsonIgnore]
- public IReadOnlyDictionary EnvironmentVariables =>
- DefaultEnvironmentVariables
- .Concat(UserEnvironmentVariables ?? [])
- .ToDictionary(x => x.Key, x => x.Value);
+ public IReadOnlyDictionary EnvironmentVariables
+ {
+ get
+ {
+ if (UserEnvironmentVariables is null || UserEnvironmentVariables.Count == 0)
+ {
+ return DefaultEnvironmentVariables;
+ }
+
+ return DefaultEnvironmentVariables
+ .Concat(UserEnvironmentVariables)
+ .GroupBy(pair => pair.Key)
+ // User variables override default variables with the same key
+ .ToDictionary(grouping => grouping.Key, grouping => grouping.Last().Value);
+ }
+ }
public HashSet? InstalledModelHashes { get; set; } = new();
diff --git a/StabilityMatrix.Core/Models/SharedFolderType.cs b/StabilityMatrix.Core/Models/SharedFolderType.cs
index 50ba7db73..f94b46d81 100644
--- a/StabilityMatrix.Core/Models/SharedFolderType.cs
+++ b/StabilityMatrix.Core/Models/SharedFolderType.cs
@@ -39,6 +39,7 @@ public enum SharedFolderType
InvokeIpAdapters15 = 1 << 24,
InvokeIpAdaptersXl = 1 << 25,
InvokeClipVision = 1 << 26,
+ SVD = 1 << 27,
PromptExpansion = 1 << 30
}
diff --git a/StabilityMatrix.Core/Models/SharedOutputType.cs b/StabilityMatrix.Core/Models/SharedOutputType.cs
index d4dede8a9..c533de495 100644
--- a/StabilityMatrix.Core/Models/SharedOutputType.cs
+++ b/StabilityMatrix.Core/Models/SharedOutputType.cs
@@ -8,6 +8,7 @@ public enum SharedOutputType
Extras,
Text2ImgGrids,
Img2ImgGrids,
+ SVD,
Saved,
Consolidated
}