Browse Source

Merge pull request #607 from ionite34/dev

2.10.1
pull/629/head
JT 7 months ago committed by GitHub
parent
commit
e626c47305
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 13
      CHANGELOG.md
  2. 5
      StabilityMatrix.Avalonia/Controls/Inference/ImageFolderCard.axaml
  3. 1
      StabilityMatrix.Avalonia/Converters/FileUriConverter.cs
  4. 1
      StabilityMatrix.Avalonia/Services/INavigationService.cs
  5. 3
      StabilityMatrix.Avalonia/Services/NavigationService.cs
  6. 2
      StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/CivitAiBrowserViewModel.cs
  7. 13
      StabilityMatrix.Avalonia/ViewModels/CheckpointManager/CheckpointFile.cs
  8. 19
      StabilityMatrix.Avalonia/ViewModels/CheckpointManager/CheckpointFolder.cs
  9. 11
      StabilityMatrix.Avalonia/ViewModels/Dialogs/LykosLoginViewModel.cs
  10. 5
      StabilityMatrix.Avalonia/ViewModels/OpenArtBrowserViewModel.cs
  11. 23
      StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageCardViewModel.cs
  12. 7
      StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageInstallDetailViewModel.cs
  13. 5
      StabilityMatrix.Avalonia/Views/CheckpointsPage.axaml
  14. 1
      StabilityMatrix.Avalonia/Views/Dialogs/LykosLoginDialog.axaml
  15. 8
      StabilityMatrix.Avalonia/Views/OutputsPage.axaml
  16. 7
      StabilityMatrix.Avalonia/Views/PackageManagerPage.axaml
  17. 33
      StabilityMatrix.Avalonia/Views/Settings/MainSettingsPage.axaml
  18. 24
      StabilityMatrix.Core/Api/TokenAuthHeaderHandler.cs
  19. 2
      StabilityMatrix.Core/Models/DownloadPackageVersionOptions.cs
  20. 8
      StabilityMatrix.Core/Models/Packages/A3WebUI.cs
  21. 48
      StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs
  22. 2
      StabilityMatrix.Core/Models/Packages/BasePackage.cs
  23. 4
      StabilityMatrix.Core/Models/Packages/ComfyUI.cs
  24. 1
      StabilityMatrix.Core/Models/Packages/Fooocus.cs
  25. 1
      StabilityMatrix.Core/Models/Packages/FooocusMre.cs
  26. 3
      StabilityMatrix.Core/Models/Packages/KohyaSs.cs
  27. 2
      StabilityMatrix.Core/Models/Packages/OneTrainer.cs
  28. 1
      StabilityMatrix.Core/Models/Packages/RuinedFooocus.cs
  29. 13
      StabilityMatrix.Core/Models/Packages/SDWebForge.cs
  30. 2
      StabilityMatrix.Core/Models/Packages/StableDiffusionDirectMl.cs
  31. 2
      StabilityMatrix.Core/Models/Packages/StableDiffusionUx.cs
  32. 17
      StabilityMatrix.Core/Models/Packages/UnknownPackage.cs
  33. 8
      StabilityMatrix.Core/Models/Packages/VoltaML.cs
  34. 20
      StabilityMatrix.Core/Models/Settings/Settings.cs
  35. 1
      StabilityMatrix.Core/Models/SharedFolderType.cs
  36. 1
      StabilityMatrix.Core/Models/SharedOutputType.cs

13
CHANGELOG.md

@ -6,9 +6,22 @@ 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). and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2.0.0.html).
## v2.10.1 ## 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
- 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 [#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 [#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 ## v2.10.0
### Added ### Added

5
StabilityMatrix.Avalonia/Controls/Inference/ImageFolderCard.axaml

@ -11,6 +11,7 @@
xmlns:scroll="clr-namespace:StabilityMatrix.Avalonia.Controls.Scroll" xmlns:scroll="clr-namespace:StabilityMatrix.Avalonia.Controls.Scroll"
xmlns:labs="clr-namespace:Avalonia.Labs.Controls;assembly=Avalonia.Labs.Controls" xmlns:labs="clr-namespace:Avalonia.Labs.Controls;assembly=Avalonia.Labs.Controls"
xmlns:vendorLabs="clr-namespace:StabilityMatrix.Avalonia.Controls.VendorLabs" xmlns:vendorLabs="clr-namespace:StabilityMatrix.Avalonia.Controls.VendorLabs"
xmlns:converters="clr-namespace:StabilityMatrix.Avalonia.Converters"
x:DataType="vmInference:ImageFolderCardViewModel"> x:DataType="vmInference:ImageFolderCardViewModel">
<Design.PreviewWith> <Design.PreviewWith>
@ -20,6 +21,8 @@
</Grid> </Grid>
</Panel> </Panel>
</Design.PreviewWith> </Design.PreviewWith>
<converters:FileUriConverter x:Key="FileUriConverter" />
<ControlTheme x:Key="{x:Type controls:ImageFolderCard}" TargetType="controls:ImageFolderCard"> <ControlTheme x:Key="{x:Type controls:ImageFolderCard}" TargetType="controls:ImageFolderCard">
<Setter Property="Background" Value="Transparent" /> <Setter Property="Background" Value="Transparent" />
@ -200,7 +203,7 @@
<vendorLabs:BetterAsyncImage <vendorLabs:BetterAsyncImage
Width="{Binding $parent[ItemsRepeater].((vmInference:ImageFolderCardViewModel)DataContext).ImageSize.Width}" Width="{Binding $parent[ItemsRepeater].((vmInference:ImageFolderCardViewModel)DataContext).ImageSize.Width}"
Height="{Binding $parent[ItemsRepeater].((vmInference:ImageFolderCardViewModel)DataContext).ImageSize.Height}" Height="{Binding $parent[ItemsRepeater].((vmInference:ImageFolderCardViewModel)DataContext).ImageSize.Height}"
Source="{Binding AbsolutePath}" Source="{Binding AbsolutePath, Converter={StaticResource FileUriConverter}}"
Stretch="UniformToFill" /> Stretch="UniformToFill" />
<Border <Border

1
StabilityMatrix.Avalonia/Converters/FileUriConverter.cs

@ -17,6 +17,7 @@ public class FileUriConverter : IValueConverter
return value switch return value switch
{ {
string str when str.StartsWith("avares://") => new Uri(str),
string str => new Uri("file://" + str), string str => new Uri("file://" + str),
IFormattable formattable => new Uri("file://" + formattable.ToString(null, culture)), IFormattable formattable => new Uri("file://" + formattable.ToString(null, culture)),
_ => null _ => null

1
StabilityMatrix.Avalonia/Services/INavigationService.cs

@ -39,4 +39,5 @@ public interface INavigationService<[SuppressMessage("ReSharper", "UnusedTypePar
bool GoBack(); bool GoBack();
bool CanGoBack { get; } bool CanGoBack { get; }
object? CurrentPageDataContext { get; }
} }

3
StabilityMatrix.Avalonia/Services/NavigationService.cs

@ -1,5 +1,6 @@
using System; using System;
using System.Linq; using System.Linq;
using Avalonia.Controls;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using FluentAvalonia.UI.Media.Animation; using FluentAvalonia.UI.Media.Animation;
using FluentAvalonia.UI.Navigation; using FluentAvalonia.UI.Navigation;
@ -190,4 +191,6 @@ public class NavigationService<T> : INavigationService<T>
} }
public bool CanGoBack => _frame?.CanGoBack ?? false; public bool CanGoBack => _frame?.CanGoBack ?? false;
public object? CurrentPageDataContext => (_frame?.Content as Control)?.DataContext;
} }

2
StabilityMatrix.Avalonia/ViewModels/CheckpointBrowser/CivitAiBrowserViewModel.cs

@ -177,6 +177,8 @@ public partial class CivitAiBrowserViewModel : TabViewModelBase, IInfinitelyScro
model => model.ShowNsfw, model => model.ShowNsfw,
settings => settings.ModelBrowserNsfwEnabled settings => settings.ModelBrowserNsfwEnabled
); );
SearchModelsCommand.ExecuteAsync(false);
} }
/// <summary> /// <summary>

13
StabilityMatrix.Avalonia/ViewModels/CheckpointManager/CheckpointFile.cs

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text.Json;
using System.Threading.Tasks; using System.Threading.Tasks;
using Avalonia.Data; using Avalonia.Data;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
@ -10,7 +11,6 @@ using CommunityToolkit.Mvvm.Input;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using NLog; using NLog;
using StabilityMatrix.Avalonia.Languages;
using StabilityMatrix.Avalonia.ViewModels.Base; using StabilityMatrix.Avalonia.ViewModels.Base;
using StabilityMatrix.Core.Attributes; using StabilityMatrix.Core.Attributes;
using StabilityMatrix.Core.Extensions; using StabilityMatrix.Core.Extensions;
@ -333,8 +333,15 @@ public partial class CheckpointFile : ViewModelBase
if (File.Exists(jsonPath)) if (File.Exists(jsonPath))
{ {
var json = File.ReadAllText(jsonPath); var json = File.ReadAllText(jsonPath);
var connectedModelInfo = ConnectedModelInfo.FromJson(json); try
checkpointFile.ConnectedModel = connectedModelInfo; {
var connectedModelInfo = ConnectedModelInfo.FromJson(json);
checkpointFile.ConnectedModel = connectedModelInfo;
}
catch (JsonException)
{
checkpointFile.ConnectedModel = null;
}
} }
checkpointFile.PreviewImagePath = SupportedImageExtensions checkpointFile.PreviewImagePath = SupportedImageExtensions

19
StabilityMatrix.Avalonia/ViewModels/CheckpointManager/CheckpointFolder.cs

@ -92,7 +92,8 @@ public partial class CheckpointFolder : ViewModelBase
public string TitleWithFilesCount => public string TitleWithFilesCount =>
CheckpointFiles.Any() || SubFolders.Any(f => f.CheckpointFiles.Any()) 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(); : FolderType.GetDescription() ?? FolderType.GetStringValue();
public ProgressViewModel Progress { get; } = new(); public ProgressViewModel Progress { get; } = new();
@ -447,6 +448,22 @@ public partial class CheckpointFolder : ViewModelBase
Progress.Value = 0; Progress.Value = 0;
var copyPaths = files.ToDictionary(k => k, v => Path.Combine(DirectoryPath, Path.GetFileName(v))); 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<ProgressReport>(report => var progress = new Progress<ProgressReport>(report =>
{ {
Progress.IsIndeterminate = false; Progress.IsIndeterminate = false;

11
StabilityMatrix.Avalonia/ViewModels/Dialogs/LykosLoginViewModel.cs

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Net;
using System.Threading.Tasks; using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
@ -90,7 +91,15 @@ public partial class LykosLoginViewModel : TaskDialogViewModelBase
} }
catch (ApiException e) 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}")
};
} }
} }

5
StabilityMatrix.Avalonia/ViewModels/OpenArtBrowserViewModel.cs

@ -12,7 +12,6 @@ using DynamicData.Binding;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using Refit; using Refit;
using StabilityMatrix.Avalonia.Controls; using StabilityMatrix.Avalonia.Controls;
using StabilityMatrix.Avalonia.Languages;
using StabilityMatrix.Avalonia.Models; using StabilityMatrix.Avalonia.Models;
using StabilityMatrix.Avalonia.Services; using StabilityMatrix.Avalonia.Services;
using StabilityMatrix.Avalonia.ViewModels.Base; using StabilityMatrix.Avalonia.ViewModels.Base;
@ -36,8 +35,7 @@ public partial class OpenArtBrowserViewModel(
IOpenArtApi openArtApi, IOpenArtApi openArtApi,
INotificationService notificationService, INotificationService notificationService,
ISettingsManager settingsManager, ISettingsManager settingsManager,
IPackageFactory packageFactory, IPackageFactory packageFactory
ServiceManager<ViewModelBase> vmFactory
) : TabViewModelBase, IInfinitelyScroll ) : TabViewModelBase, IInfinitelyScroll
{ {
private const int PageSize = 20; private const int PageSize = 20;
@ -90,6 +88,7 @@ public partial class OpenArtBrowserViewModel(
{ {
searchResultsCache.Connect().DeferUntilLoaded().Bind(SearchResults).Subscribe(); searchResultsCache.Connect().DeferUntilLoaded().Bind(SearchResults).Subscribe();
SelectedSortMode = AllSortModes.First(); SelectedSortMode = AllSortModes.First();
DoSearch().SafeFireAndForget();
} }
[RelayCommand] [RelayCommand]

23
StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageCardViewModel.cs

@ -95,6 +95,9 @@ public partial class PackageCardViewModel(
[ObservableProperty] [ObservableProperty]
private bool showWebUiButton; private bool showWebUiButton;
[ObservableProperty]
private DownloadPackageVersionOptions? updateVersion;
private void RunningPackagesOnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) private void RunningPackagesOnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{ {
if (runningPackageService.RunningPackages.Select(x => x.Value) is not { } runningPackages) if (runningPackageService.RunningPackages.Select(x => x.Value) is not { } runningPackages)
@ -196,6 +199,10 @@ public partial class PackageCardViewModel(
} }
IsUpdateAvailable = await HasUpdate(); IsUpdateAvailable = await HasUpdate();
if (IsUpdateAvailable)
{
UpdateVersion = await basePackage.GetUpdate(currentPackage);
}
if ( if (
Package != null Package != null
@ -426,21 +433,6 @@ public partial class PackageCardViewModel(
versionOptions.CommitHash = latest.Sha; 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( var updatePackageStep = new UpdatePackageStep(
settingsManager, settingsManager,
Package, Package,
@ -672,6 +664,7 @@ public partial class PackageCardViewModel(
try try
{ {
var hasUpdate = await basePackage.CheckForUpdates(Package); var hasUpdate = await basePackage.CheckForUpdates(Package);
UpdateVersion = await basePackage.GetUpdate(Package);
await using (settingsManager.BeginTransaction()) await using (settingsManager.BeginTransaction())
{ {

7
StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageInstallDetailViewModel.cs

@ -283,6 +283,13 @@ public partial class PackageInstallDetailViewModel(
if (!runner.Failed) if (!runner.Failed)
{ {
if (ReferenceEquals(this, packageNavigationService.CurrentPageDataContext))
{
packageNavigationService.GoBack();
packageNavigationService.GoBack();
await Task.Delay(100);
}
EventManager.Instance.OnInstalledPackagesChanged(); EventManager.Instance.OnInstalledPackagesChanged();
} }
} }

5
StabilityMatrix.Avalonia/Views/CheckpointsPage.axaml

@ -31,6 +31,7 @@
x:Key="TextDropShadowEffect" /> x:Key="TextDropShadowEffect" />
<converters:EnumStringConverter x:Key="EnumStringConverter" /> <converters:EnumStringConverter x:Key="EnumStringConverter" />
<converters:FileUriConverter x:Key="FileUriConverter"/>
<!-- Template for a single badge --> <!-- Template for a single badge -->
<DataTemplate DataType="{x:Type system:String}" x:Key="BadgeTemplate"> <DataTemplate DataType="{x:Type system:String}" x:Key="BadgeTemplate">
@ -143,7 +144,7 @@
<vendorLabs:BetterAsyncImage <vendorLabs:BetterAsyncImage
Margin="0,0,0,4" Margin="0,0,0,4"
CornerRadius="4" CornerRadius="4"
Source="{Binding PreviewImagePath}" Source="{Binding PreviewImagePath, Converter={StaticResource FileUriConverter}}"
Stretch="Uniform" Stretch="Uniform"
IsVisible="{Binding IsConnectedModel}" /> IsVisible="{Binding IsConnectedModel}" />
<TextBlock <TextBlock
@ -182,7 +183,7 @@
Grid.ColumnSpan="2" Grid.ColumnSpan="2"
Margin="0, 4,0,4" Margin="0, 4,0,4"
CornerRadius="8" CornerRadius="8"
Source="{Binding PreviewImagePath}" Source="{Binding PreviewImagePath, Converter={StaticResource FileUriConverter}}"
ClipToBounds="True" ClipToBounds="True"
Stretch="UniformToFill" Stretch="UniformToFill"
Height="300" Height="300"

1
StabilityMatrix.Avalonia/Views/Dialogs/LykosLoginDialog.axaml

@ -14,6 +14,7 @@
xmlns:mdxaml="https://github.com/whistyun/Markdown.Avalonia.Tight" xmlns:mdxaml="https://github.com/whistyun/Markdown.Avalonia.Tight"
xmlns:ctxt="clr-namespace:ColorTextBlock.Avalonia;assembly=ColorTextBlock.Avalonia" xmlns:ctxt="clr-namespace:ColorTextBlock.Avalonia;assembly=ColorTextBlock.Avalonia"
Focusable="True" Focusable="True"
MaxWidth="400"
d:DataContext="{x:Static mocks:DesignData.LykosLoginViewModel}" d:DataContext="{x:Static mocks:DesignData.LykosLoginViewModel}"
d:DesignHeight="350" d:DesignHeight="350"
d:DesignWidth="400" d:DesignWidth="400"

8
StabilityMatrix.Avalonia/Views/OutputsPage.axaml

@ -13,6 +13,7 @@
xmlns:selectableImageCard="clr-namespace:StabilityMatrix.Avalonia.Controls.SelectableImageCard" xmlns:selectableImageCard="clr-namespace:StabilityMatrix.Avalonia.Controls.SelectableImageCard"
xmlns:ui="using:FluentAvalonia.UI.Controls" xmlns:ui="using:FluentAvalonia.UI.Controls"
xmlns:vm="clr-namespace:StabilityMatrix.Avalonia.ViewModels" xmlns:vm="clr-namespace:StabilityMatrix.Avalonia.ViewModels"
xmlns:converters="clr-namespace:StabilityMatrix.Avalonia.Converters"
d:DataContext="{x:Static mocks:DesignData.OutputsPageViewModel}" d:DataContext="{x:Static mocks:DesignData.OutputsPageViewModel}"
d:DesignHeight="650" d:DesignHeight="650"
d:DesignWidth="800" d:DesignWidth="800"
@ -20,6 +21,11 @@
x:DataType="vm:OutputsPageViewModel" x:DataType="vm:OutputsPageViewModel"
Focusable="True" Focusable="True"
mc:Ignorable="d"> mc:Ignorable="d">
<controls:UserControlBase.Resources>
<converters:FileUriConverter x:Key="FileUriConverter" />
</controls:UserControlBase.Resources>
<Grid Margin="16" RowDefinitions="Auto,*" <Grid Margin="16" RowDefinitions="Auto,*"
ColumnDefinitions="Auto, *"> ColumnDefinitions="Auto, *">
@ -177,7 +183,7 @@
ImageHeight="{Binding $parent[ItemsRepeater].((vm:OutputsPageViewModel)DataContext).ImageSize.Height}" ImageHeight="{Binding $parent[ItemsRepeater].((vm:OutputsPageViewModel)DataContext).ImageSize.Height}"
ImageWidth="{Binding $parent[ItemsRepeater].((vm:OutputsPageViewModel)DataContext).ImageSize.Width}" ImageWidth="{Binding $parent[ItemsRepeater].((vm:OutputsPageViewModel)DataContext).ImageSize.Width}"
IsSelected="{Binding IsSelected}" IsSelected="{Binding IsSelected}"
Source="{Binding ImageFile.AbsolutePath}"> Source="{Binding ImageFile.AbsolutePath, Converter={StaticResource FileUriConverter}}">
<selectableImageCard:SelectableImageButton.ContextFlyout> <selectableImageCard:SelectableImageButton.ContextFlyout>
<ui:FAMenuFlyout> <ui:FAMenuFlyout>
<ui:MenuFlyoutItem <ui:MenuFlyoutItem

7
StabilityMatrix.Avalonia/Views/PackageManagerPage.axaml

@ -255,9 +255,14 @@
Margin="4,4,0,0" Margin="4,4,0,0"
Padding="4" Padding="4"
IsEnabled="{Binding !IsRunning}" IsEnabled="{Binding !IsRunning}"
ToolTip.Tip="{x:Static lang:Resources.Label_UpdateAvailable}"
markupExtensions:ShowDisabledTooltipExtension.ShowOnDisabled="True" markupExtensions:ShowDisabledTooltipExtension.ShowOnDisabled="True"
Command="{Binding Update}"> Command="{Binding Update}">
<ToolTip.Tip>
<TextBlock>
<Run Text="{x:Static lang:Resources.Label_UpdateAvailable}"/>
<Run Text="(" /><Run Text="{Binding UpdateVersion.ReadableVersionString, FallbackValue=Unknown}"/><Run Text=")"/>
</TextBlock>
</ToolTip.Tip>
<Button.IsVisible> <Button.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.And}"> <MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="!IsUnknownPackage" /> <Binding Path="!IsUnknownPackage" />

33
StabilityMatrix.Avalonia/Views/Settings/MainSettingsPage.axaml

@ -82,19 +82,6 @@
Symbol="Alert" /> Symbol="Alert" />
</ui:SettingsExpander.IconSource> </ui:SettingsExpander.IconSource>
</ui:SettingsExpander> </ui:SettingsExpander>
<ui:SettingsExpander Grid.Row="3"
Header="{x:Static lang:Resources.Label_HolidayMode}">
<ui:SettingsExpander.IconSource>
<fluentIcons:SymbolIconSource
FontSize="10"
IsFilled="True"
Symbol="WeatherSnowflake" />
</ui:SettingsExpander.IconSource>
<ui:SettingsExpander.Footer>
<ui:FAComboBox SelectedItem="{Binding HolidayModeSetting}"
ItemsSource="{Binding HolidayModes}"/>
</ui:SettingsExpander.Footer>
</ui:SettingsExpander>
</sg:SpacedGrid> </sg:SpacedGrid>
<!-- Integrations --> <!-- Integrations -->
@ -215,7 +202,7 @@
</sg:SpacedGrid> </sg:SpacedGrid>
<!-- Theme --> <!-- Theme -->
<Grid RowDefinitions="Auto,*,*,*"> <Grid RowDefinitions="Auto,*,*,*,*">
<TextBlock <TextBlock
Margin="0,0,0,8" Margin="0,0,0,8"
FontWeight="Medium" FontWeight="Medium"
@ -245,8 +232,24 @@
SelectedItem="{Binding SelectedLanguage}" /> SelectedItem="{Binding SelectedLanguage}" />
</ui:SettingsExpander.Footer> </ui:SettingsExpander.Footer>
</ui:SettingsExpander> </ui:SettingsExpander>
<ui:SettingsExpander Grid.Row="3"
Margin="8,0,8,4"
Header="{x:Static lang:Resources.Label_HolidayMode}">
<ui:SettingsExpander.IconSource>
<fluentIcons:SymbolIconSource
FontSize="10"
IsFilled="True"
Symbol="WeatherSnowflake" />
</ui:SettingsExpander.IconSource>
<ui:SettingsExpander.Footer>
<ui:FAComboBox SelectedItem="{Binding HolidayModeSetting}"
ItemsSource="{Binding HolidayModes}"/>
</ui:SettingsExpander.Footer>
</ui:SettingsExpander>
<ui:SettingsExpander <ui:SettingsExpander
Grid.Row="3" Grid.Row="4"
Margin="8,0,8,4" Margin="8,0,8,4"
ActionIconSource="ChevronRight" ActionIconSource="ChevronRight"
Command="{Binding NavigateToSubPageCommand}" Command="{Binding NavigateToSubPageCommand}"

24
StabilityMatrix.Core/Api/TokenAuthHeaderHandler.cs

@ -22,8 +22,8 @@ public class TokenAuthHeaderHandler : DelegatingHandler
.HandleResult<HttpResponseMessage>( .HandleResult<HttpResponseMessage>(
r => r =>
r.StatusCode is HttpStatusCode.Unauthorized or HttpStatusCode.Forbidden r.StatusCode is HttpStatusCode.Unauthorized or HttpStatusCode.Forbidden
&& r.RequestMessage?.Headers.Authorization && r.RequestMessage?.Headers.Authorization is { Scheme: "Bearer", Parameter: { } param }
is { Scheme: "Bearer", Parameter: not null } && !string.IsNullOrWhiteSpace(param)
) )
.RetryAsync( .RetryAsync(
async (result, _) => async (result, _) =>
@ -35,9 +35,7 @@ public class TokenAuthHeaderHandler : DelegatingHandler
"Refreshing access token for status ({StatusCode})", "Refreshing access token for status ({StatusCode})",
result.Result.StatusCode result.Result.StatusCode
); );
var (newToken, _) = await tokenProvider var (newToken, _) = await tokenProvider.RefreshTokensAsync().ConfigureAwait(false);
.RefreshTokensAsync()
.ConfigureAwait(false);
Logger.Info( Logger.Info(
"Access token refreshed: {OldToken} -> {NewToken}", "Access token refreshed: {OldToken} -> {NewToken}",
@ -46,10 +44,6 @@ public class TokenAuthHeaderHandler : DelegatingHandler
); );
} }
); );
// InnerHandler must be left as null when using DI, but must be assigned a value when
// using RestService.For<IMyApi>
// InnerHandler = new HttpClientHandler();
} }
protected override Task<HttpResponseMessage> SendAsync( protected override Task<HttpResponseMessage> SendAsync(
@ -59,9 +53,17 @@ public class TokenAuthHeaderHandler : DelegatingHandler
{ {
return policy.ExecuteAsync(async () => 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); return await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
}); });

2
StabilityMatrix.Core/Models/DownloadPackageVersionOptions.cs

@ -10,4 +10,6 @@ public class DownloadPackageVersionOptions
public string GetReadableVersionString() => public string GetReadableVersionString() =>
!string.IsNullOrWhiteSpace(VersionTag) ? VersionTag : $"{BranchName}@{CommitHash?[..7]}"; !string.IsNullOrWhiteSpace(VersionTag) ? VersionTag : $"{BranchName}@{CommitHash?[..7]}";
public string ReadableVersionString => GetReadableVersionString();
} }

8
StabilityMatrix.Core/Models/Packages/A3WebUI.cs

@ -66,7 +66,8 @@ public class A3WebUI(
[SharedFolderType.T2IAdapter] = new[] { "models/controlnet/T2IAdapter" }, [SharedFolderType.T2IAdapter] = new[] { "models/controlnet/T2IAdapter" },
[SharedFolderType.IpAdapter] = new[] { "models/controlnet/IpAdapter" }, [SharedFolderType.IpAdapter] = new[] { "models/controlnet/IpAdapter" },
[SharedFolderType.InvokeIpAdapters15] = new[] { "models/controlnet/DiffusersIpAdapters" }, [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<SharedOutputType, IReadOnlyList<string>>? SharedOutputFolders => public override Dictionary<SharedOutputType, IReadOnlyList<string>>? SharedOutputFolders =>
@ -77,7 +78,8 @@ public class A3WebUI(
[SharedOutputType.Img2Img] = new[] { "output/img2img-images" }, [SharedOutputType.Img2Img] = new[] { "output/img2img-images" },
[SharedOutputType.Text2Img] = new[] { "output/txt2img-images" }, [SharedOutputType.Text2Img] = new[] { "output/txt2img-images" },
[SharedOutputType.Img2ImgGrids] = new[] { "output/img2img-grids" }, [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")] [SuppressMessage("ReSharper", "ArrangeObjectCreationWhenTypeNotEvident")]
@ -204,6 +206,8 @@ public class A3WebUI(
await using var venvRunner = new PyVenvRunner(venvPath); await using var venvRunner = new PyVenvRunner(venvPath);
venvRunner.WorkingDirectory = installLocation; venvRunner.WorkingDirectory = installLocation;
venvRunner.EnvironmentVariables = settingsManager.Settings.EnvironmentVariables;
await venvRunner.Setup(true, onConsoleOutput).ConfigureAwait(false); await venvRunner.Setup(true, onConsoleOutput).ConfigureAwait(false);
await venvRunner.PipInstall("--upgrade pip wheel", onConsoleOutput).ConfigureAwait(false); await venvRunner.PipInstall("--upgrade pip wheel", onConsoleOutput).ConfigureAwait(false);

48
StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs

@ -345,6 +345,54 @@ public abstract class BaseGitPackage : BasePackage
} }
} }
public override async Task<DownloadPackageVersionOptions?> 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<InstalledPackageVersion> Update( public override async Task<InstalledPackageVersion> Update(
InstalledPackage installedPackage, InstalledPackage installedPackage,
TorchVersion torchVersion, TorchVersion torchVersion,

2
StabilityMatrix.Core/Models/Packages/BasePackage.cs

@ -237,4 +237,6 @@ public abstract class BasePackage
onConsoleOutput onConsoleOutput
); );
} }
public abstract Task<DownloadPackageVersionOptions?> GetUpdate(InstalledPackage installedPackage);
} }

4
StabilityMatrix.Core/Models/Packages/ComfyUI.cs

@ -195,8 +195,9 @@ public class ComfyUI(
// Setup venv // Setup venv
await using var venvRunner = new PyVenvRunner(Path.Combine(installLocation, "venv")); await using var venvRunner = new PyVenvRunner(Path.Combine(installLocation, "venv"));
venvRunner.WorkingDirectory = installLocation; 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); await venvRunner.PipInstall("--upgrade pip wheel", onConsoleOutput).ConfigureAwait(false);
progress?.Report( progress?.Report(
@ -245,6 +246,7 @@ public class ComfyUI(
excludePattern: "torch" excludePattern: "torch"
); );
await venvRunner.PipUninstall("xformers", onConsoleOutput).ConfigureAwait(false);
await venvRunner.PipInstall(pipArgs, onConsoleOutput).ConfigureAwait(false); await venvRunner.PipInstall(pipArgs, onConsoleOutput).ConfigureAwait(false);
progress?.Report(new ProgressReport(1, "Installed Package Requirements", isIndeterminate: false)); progress?.Report(new ProgressReport(1, "Installed Package Requirements", isIndeterminate: false));

1
StabilityMatrix.Core/Models/Packages/Fooocus.cs

@ -193,6 +193,7 @@ public class Fooocus(
) )
{ {
var venvRunner = await SetupVenv(installLocation, forceRecreate: true).ConfigureAwait(false); var venvRunner = await SetupVenv(installLocation, forceRecreate: true).ConfigureAwait(false);
venvRunner.EnvironmentVariables = settingsManager.Settings.EnvironmentVariables;
progress?.Report(new ProgressReport(-1f, "Installing requirements...", isIndeterminate: true)); progress?.Report(new ProgressReport(-1f, "Installing requirements...", isIndeterminate: true));

1
StabilityMatrix.Core/Models/Packages/FooocusMre.cs

@ -111,6 +111,7 @@ public class FooocusMre(
) )
{ {
var venvRunner = await SetupVenv(installLocation, forceRecreate: true).ConfigureAwait(false); var venvRunner = await SetupVenv(installLocation, forceRecreate: true).ConfigureAwait(false);
venvRunner.EnvironmentVariables = settingsManager.Settings.EnvironmentVariables;
progress?.Report(new ProgressReport(-1f, "Installing torch...", isIndeterminate: true)); progress?.Report(new ProgressReport(-1f, "Installing torch...", isIndeterminate: true));

3
StabilityMatrix.Core/Models/Packages/KohyaSs.cs

@ -126,9 +126,12 @@ public class KohyaSs(
.ConfigureAwait(false); .ConfigureAwait(false);
progress?.Report(new ProgressReport(-1f, "Setting up venv", isIndeterminate: true)); progress?.Report(new ProgressReport(-1f, "Setting up venv", isIndeterminate: true));
// Setup venv // Setup venv
await using var venvRunner = new PyVenvRunner(Path.Combine(installLocation, "venv")); await using var venvRunner = new PyVenvRunner(Path.Combine(installLocation, "venv"));
venvRunner.WorkingDirectory = installLocation; venvRunner.WorkingDirectory = installLocation;
venvRunner.EnvironmentVariables = settingsManager.Settings.EnvironmentVariables;
await venvRunner.Setup(true, onConsoleOutput).ConfigureAwait(false); await venvRunner.Setup(true, onConsoleOutput).ConfigureAwait(false);
// Extra dep needed before running setup since v23.0.x // Extra dep needed before running setup since v23.0.x

2
StabilityMatrix.Core/Models/Packages/OneTrainer.cs

@ -57,6 +57,8 @@ public class OneTrainer(
await using var venvRunner = new PyVenvRunner(Path.Combine(installLocation, "venv")); await using var venvRunner = new PyVenvRunner(Path.Combine(installLocation, "venv"));
venvRunner.WorkingDirectory = installLocation; venvRunner.WorkingDirectory = installLocation;
venvRunner.EnvironmentVariables = settingsManager.Settings.EnvironmentVariables;
await venvRunner.Setup(true, onConsoleOutput).ConfigureAwait(false); await venvRunner.Setup(true, onConsoleOutput).ConfigureAwait(false);
progress?.Report(new ProgressReport(-1f, "Installing requirements", isIndeterminate: true)); progress?.Report(new ProgressReport(-1f, "Installing requirements", isIndeterminate: true));

1
StabilityMatrix.Core/Models/Packages/RuinedFooocus.cs

@ -116,6 +116,7 @@ public class RuinedFooocus(
if (torchVersion == TorchVersion.Cuda) if (torchVersion == TorchVersion.Cuda)
{ {
var venvRunner = await SetupVenv(installLocation, forceRecreate: true).ConfigureAwait(false); var venvRunner = await SetupVenv(installLocation, forceRecreate: true).ConfigureAwait(false);
venvRunner.EnvironmentVariables = settingsManager.Settings.EnvironmentVariables;
progress?.Report(new ProgressReport(-1f, "Installing requirements...", isIndeterminate: true)); progress?.Report(new ProgressReport(-1f, "Installing requirements...", isIndeterminate: true));

13
StabilityMatrix.Core/Models/Packages/SDWebForge.cs

@ -41,17 +41,6 @@ public class SDWebForge(
public override string OutputFolderName => "output"; public override string OutputFolderName => "output";
public override PackageDifficulty InstallerSortOrder => PackageDifficulty.ReallyRecommended; public override PackageDifficulty InstallerSortOrder => PackageDifficulty.ReallyRecommended;
public override Dictionary<SharedOutputType, IReadOnlyList<string>>? 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<LaunchOptionDefinition> LaunchOptions => public override List<LaunchOptionDefinition> LaunchOptions =>
[ [
new LaunchOptionDefinition new LaunchOptionDefinition
@ -142,6 +131,8 @@ public class SDWebForge(
await using var venvRunner = new PyVenvRunner(venvPath); await using var venvRunner = new PyVenvRunner(venvPath);
venvRunner.WorkingDirectory = installLocation; venvRunner.WorkingDirectory = installLocation;
venvRunner.EnvironmentVariables = settingsManager.Settings.EnvironmentVariables;
await venvRunner.Setup(true, onConsoleOutput).ConfigureAwait(false); await venvRunner.Setup(true, onConsoleOutput).ConfigureAwait(false);
await venvRunner.PipInstall("--upgrade pip wheel", onConsoleOutput).ConfigureAwait(false); await venvRunner.PipInstall("--upgrade pip wheel", onConsoleOutput).ConfigureAwait(false);

2
StabilityMatrix.Core/Models/Packages/StableDiffusionDirectMl.cs

@ -76,6 +76,8 @@ public class StableDiffusionDirectMl(
// Setup venv // Setup venv
await using var venvRunner = new PyVenvRunner(Path.Combine(installLocation, "venv")); await using var venvRunner = new PyVenvRunner(Path.Combine(installLocation, "venv"));
venvRunner.WorkingDirectory = installLocation; venvRunner.WorkingDirectory = installLocation;
venvRunner.EnvironmentVariables = settingsManager.Settings.EnvironmentVariables;
await venvRunner.Setup(true, onConsoleOutput).ConfigureAwait(false); await venvRunner.Setup(true, onConsoleOutput).ConfigureAwait(false);
switch (torchVersion) switch (torchVersion)

2
StabilityMatrix.Core/Models/Packages/StableDiffusionUx.cs

@ -190,6 +190,8 @@ public class StableDiffusionUx(
// Setup venv // Setup venv
await using var venvRunner = new PyVenvRunner(Path.Combine(installLocation, "venv")); await using var venvRunner = new PyVenvRunner(Path.Combine(installLocation, "venv"));
venvRunner.WorkingDirectory = installLocation; venvRunner.WorkingDirectory = installLocation;
venvRunner.EnvironmentVariables = settingsManager.Settings.EnvironmentVariables;
await venvRunner.Setup(true, onConsoleOutput).ConfigureAwait(false); await venvRunner.Setup(true, onConsoleOutput).ConfigureAwait(false);
switch (torchVersion) switch (torchVersion)

17
StabilityMatrix.Core/Models/Packages/UnknownPackage.cs

@ -15,8 +15,7 @@ public class UnknownPackage : BasePackage
public override string GithubUrl => ""; public override string GithubUrl => "";
public override string LicenseType => "AGPL-3.0"; public override string LicenseType => "AGPL-3.0";
public override string LicenseUrl => public override string LicenseUrl => "https://github.com/LykosAI/StabilityMatrix/blob/main/LICENSE";
"https://github.com/LykosAI/StabilityMatrix/blob/main/LICENSE";
public override string Blurb => "A dank interface for diffusion"; public override string Blurb => "A dank interface for diffusion";
public override string LaunchCommand => "test"; public override string LaunchCommand => "test";
@ -140,20 +139,20 @@ public class UnknownPackage : BasePackage
public override List<LaunchOptionDefinition> LaunchOptions => new(); public override List<LaunchOptionDefinition> LaunchOptions => new();
public override Dictionary<SharedFolderType, IReadOnlyList<string>>? SharedFolders { get; } public override Dictionary<SharedFolderType, IReadOnlyList<string>>? SharedFolders { get; }
public override Dictionary< public override Dictionary<SharedOutputType, IReadOnlyList<string>>? SharedOutputFolders { get; }
SharedOutputType,
IReadOnlyList<string>
>? SharedOutputFolders { get; }
public override Task<DownloadPackageVersionOptions> GetLatestVersion( public override Task<DownloadPackageVersionOptions> GetLatestVersion(bool includePrerelease = false)
bool includePrerelease = false
)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override string MainBranch { get; } public override string MainBranch { get; }
public override Task<DownloadPackageVersionOptions?> GetUpdate(InstalledPackage installedPackage)
{
return Task.FromResult(new DownloadPackageVersionOptions { IsLatest = true, VersionTag = "1.8.0" });
}
public override Task<PackageVersionOptions> GetAllVersionOptions() => public override Task<PackageVersionOptions> GetAllVersionOptions() =>
Task.FromResult(new PackageVersionOptions()); Task.FromResult(new PackageVersionOptions());

8
StabilityMatrix.Core/Models/Packages/VoltaML.cs

@ -21,12 +21,15 @@ public class VoltaML(
public override string DisplayName { get; set; } = "VoltaML"; public override string DisplayName { get; set; } = "VoltaML";
public override string Author => "VoltaML"; public override string Author => "VoltaML";
public override string LicenseType => "GPL-3.0"; 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 Blurb => "Fast Stable Diffusion with support for AITemplate";
public override string LaunchCommand => "main.py"; public override string LaunchCommand => "main.py";
public override Uri PreviewImageUri => 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; public override PackageDifficulty InstallerSortOrder => PackageDifficulty.Simple;
@ -155,6 +158,7 @@ public class VoltaML(
progress?.Report(new ProgressReport(-1, "Setting up venv", isIndeterminate: true)); progress?.Report(new ProgressReport(-1, "Setting up venv", isIndeterminate: true));
await using var venvRunner = new PyVenvRunner(Path.Combine(installLocation, "venv")); await using var venvRunner = new PyVenvRunner(Path.Combine(installLocation, "venv"));
venvRunner.WorkingDirectory = installLocation; venvRunner.WorkingDirectory = installLocation;
venvRunner.EnvironmentVariables = settingsManager.Settings.EnvironmentVariables;
await venvRunner.Setup(true, onConsoleOutput).ConfigureAwait(false); await venvRunner.Setup(true, onConsoleOutput).ConfigureAwait(false);

20
StabilityMatrix.Core/Models/Settings/Settings.cs

@ -118,10 +118,22 @@ public class Settings
public Dictionary<string, string>? UserEnvironmentVariables { get; set; } public Dictionary<string, string>? UserEnvironmentVariables { get; set; }
[JsonIgnore] [JsonIgnore]
public IReadOnlyDictionary<string, string> EnvironmentVariables => public IReadOnlyDictionary<string, string> EnvironmentVariables
DefaultEnvironmentVariables {
.Concat(UserEnvironmentVariables ?? []) get
.ToDictionary(x => x.Key, x => x.Value); {
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<string>? InstalledModelHashes { get; set; } = new(); public HashSet<string>? InstalledModelHashes { get; set; } = new();

1
StabilityMatrix.Core/Models/SharedFolderType.cs

@ -39,6 +39,7 @@ public enum SharedFolderType
InvokeIpAdapters15 = 1 << 24, InvokeIpAdapters15 = 1 << 24,
InvokeIpAdaptersXl = 1 << 25, InvokeIpAdaptersXl = 1 << 25,
InvokeClipVision = 1 << 26, InvokeClipVision = 1 << 26,
SVD = 1 << 27,
PromptExpansion = 1 << 30 PromptExpansion = 1 << 30
} }

1
StabilityMatrix.Core/Models/SharedOutputType.cs

@ -8,6 +8,7 @@ public enum SharedOutputType
Extras, Extras,
Text2ImgGrids, Text2ImgGrids,
Img2ImgGrids, Img2ImgGrids,
SVD,
Saved, Saved,
Consolidated Consolidated
} }

Loading…
Cancel
Save