Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v2.4.4 Update #135

Merged
merged 12 commits into from
Sep 18, 2023
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ 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.4.4
### Added
- Added button to toggle automatic scrolling of console output
### Fixed
- Fixed [#130](https://github.com/LykosAI/StabilityMatrix/issues/130) ComfyUI extra_model_paths.yaml file being overwritten on each launch
- Fixed some package updates not showing any console output
- Fixed auto-close of update dialog when package update is complete

## v2.4.3
### Added
- Added "--no-download-sd-model" launch argument option for Stable Diffusion Web UI
Expand Down
9 changes: 9 additions & 0 deletions StabilityMatrix.Avalonia/Languages/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions StabilityMatrix.Avalonia/Languages/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -639,4 +639,7 @@
<data name="Label_Branch" xml:space="preserve">
<value>Branch</value>
</data>
<data name="Label_AutoScrollToEnd" xml:space="preserve">
<value>Automatically scroll to end of console output</value>
</data>
</root>
24 changes: 23 additions & 1 deletion StabilityMatrix.Avalonia/ViewModels/LaunchPageViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ public partial class LaunchPageViewModel : PageViewModelBase, IDisposable, IAsyn
[ObservableProperty]
private BasePackage? runningPackage;

[ObservableProperty]
private bool autoScrollToEnd;

public virtual BasePackage? SelectedBasePackage =>
PackageFactory.FindPackageByName(SelectedPackage?.PackageName);

Expand Down Expand Up @@ -126,6 +129,12 @@ ServiceManager<ViewModelBase> dialogFactory
settings => settings.ActiveInstalledPackage
);

settingsManager.RelayPropertyFor(
this,
vm => vm.AutoScrollToEnd,
settings => settings.AutoScrollLaunchConsoleToEnd
);

EventManager.Instance.PackageLaunchRequested += OnPackageLaunchRequested;
EventManager.Instance.OneClickInstallFinished += OnOneClickInstallFinished;
EventManager.Instance.InstalledPackagesChanged += OnInstalledPackagesChanged;
Expand Down Expand Up @@ -161,6 +170,14 @@ private void OnPackageLaunchRequested(object? sender, Guid e)
LaunchAsync().SafeFireAndForget();
}

partial void OnAutoScrollToEndChanged(bool value)
{
if (value)
{
EventManager.Instance.OnScrollToBottomRequested();
}
}

public override void OnLoaded()
{
// Ensure active package either exists or is null
Expand All @@ -179,6 +196,7 @@ public override void OnLoaded()

// Load active package
SelectedPackage = settingsManager.Settings.ActiveInstalledPackage;
AutoScrollToEnd = settingsManager.Settings.AutoScrollLaunchConsoleToEnd;
}

[RelayCommand]
Expand Down Expand Up @@ -487,7 +505,11 @@ private void OnProcessExited(object? sender, int exitCode)
private void OnProcessOutputReceived(ProcessOutput output)
{
Console.Post(output);
EventManager.Instance.OnScrollToBottomRequested();

if (AutoScrollToEnd)
{
EventManager.Instance.OnScrollToBottomRequested();
}
}

private void OnOneClickInstallFinished(object? sender, bool e)
Expand Down
16 changes: 10 additions & 6 deletions StabilityMatrix.Avalonia/ViewModels/PackageManagerViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,12 +143,16 @@ public async Task ShowInstallDialog()

EventManager.Instance.OnPackageInstallProgressAdded(runner);
await runner.ExecuteSteps(steps.ToList());
EventManager.Instance.OnInstalledPackagesChanged();
notificationService.Show(
"Package Install Complete",
$"{viewModel.InstallName} installed successfully",
NotificationType.Success
);

if (!runner.Failed)
{
EventManager.Instance.OnInstalledPackagesChanged();
notificationService.Show(
"Package Install Complete",
$"{viewModel.InstallName} installed successfully",
NotificationType.Success
);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ private void PackageModificationRunnerOnProgressChanged(object? sender, Progress
Progress.IsIndeterminate = e.IsIndeterminate;
Progress.Text = packageModificationRunner.CurrentStep?.ProgressTitle;
Name = packageModificationRunner.CurrentStep?.ProgressTitle;
Failed = packageModificationRunner.Failed;

if (string.IsNullOrWhiteSpace(e.Message) || e.Message.Contains("Downloading..."))
return;
Expand All @@ -51,12 +52,20 @@ private void PackageModificationRunnerOnProgressChanged(object? sender, Progress

if (
e is { Message: not null, Percentage: >= 100 }
&& e.Message.Contains("Package Install Complete")
&& e.Message.Contains(
packageModificationRunner.ModificationCompleteMessage ?? "Package Install Complete"
)
&& Progress.CloseWhenFinished
)
{
Dispatcher.UIThread.Post(() => dialog?.Hide());
}

if (Failed)
{
Progress.Text = "Package Modification Failed";
Name = "Package Modification Failed";
}
}

public async Task ShowProgressDialog()
Expand Down
15 changes: 14 additions & 1 deletion StabilityMatrix.Avalonia/Views/LaunchPageView.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
xmlns:vm="clr-namespace:StabilityMatrix.Avalonia.ViewModels"
xmlns:system="clr-namespace:System;assembly=System.Runtime"
xmlns:lang="clr-namespace:StabilityMatrix.Avalonia.Languages"
xmlns:avalonia="clr-namespace:Projektanker.Icons.Avalonia;assembly=Projektanker.Icons.Avalonia"
d:DataContext="{x:Static mocks:DesignData.LaunchPageViewModel}"
d:DesignHeight="450"
d:DesignWidth="700"
Expand All @@ -25,7 +26,7 @@
</controls:UserControlBase.Resources>

<Grid RowDefinitions="Auto,*,Auto">
<Grid ColumnDefinitions="Auto,*,Auto"
<Grid ColumnDefinitions="Auto,*,Auto,Auto"
Margin="0,8,0, 8">
<Grid ColumnDefinitions="0.8*,0.2*" Margin="16,8,0,0">
<!-- Use split if extra commands, otherwise normal launch button -->
Expand Down Expand Up @@ -145,6 +146,18 @@
<ToggleButton
Grid.Column="2"
Width="48"
Margin="8,8,0,0"
IsChecked="{Binding AutoScrollToEnd}"
ToolTip.Tip="{x:Static lang:Resources.Label_AutoScrollToEnd}"
HorizontalAlignment="Left"
VerticalAlignment="Stretch"
FontSize="16">
<avalonia:Icon Value="fa-solid fa-arrow-down-wide-short" />
</ToggleButton>

<ToggleButton
Grid.Column="3"
Width="48"
Margin="8,8,16,0"
IsChecked="{Binding ShowManualInputPrompt}"
ToolTip.Tip="{x:Static lang:Resources.Action_SendInput}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ public interface IPackageModificationRunner
List<string> ConsoleOutput { get; }
Guid Id { get; }
bool ShowDialogOnStart { get; init; }
string? ModificationCompleteMessage { get; init; }
bool Failed { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,35 @@ public async Task ExecuteSteps(IReadOnlyList<IPackageStep> steps)
foreach (var step in steps)
{
CurrentStep = step;
await step.ExecuteAsync(progress).ConfigureAwait(false);
try
{
await step.ExecuteAsync(progress).ConfigureAwait(false);
}
catch (Exception e)
{
progress.Report(
new ProgressReport(
1f,
title: "Error modifying package",
message: $"Error: {e}",
isIndeterminate: false
)
);
Failed = true;
break;
}
}

progress.Report(
new ProgressReport(
1f,
message: ModificationCompleteMessage ?? "Package Install Complete",
isIndeterminate: false
)
);
if (!Failed)
{
progress.Report(
new ProgressReport(
1f,
message: ModificationCompleteMessage ?? "Package Install Complete",
isIndeterminate: false
)
);
}

IsRunning = false;
}
Expand All @@ -39,6 +58,7 @@ public async Task ExecuteSteps(IReadOnlyList<IPackageStep> steps)
public bool ShowDialogOnStart { get; init; }

public bool IsRunning { get; set; }
public bool Failed { get; set; }
public ProgressReport CurrentProgress { get; set; }
public IPackageStep? CurrentStep { get; set; }
public List<string> ConsoleOutput { get; } = new();
Expand Down
4 changes: 2 additions & 2 deletions StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ await DownloadPackage(
)
.ConfigureAwait(false);

await InstallPackage(installedPackage.FullPath, torchVersion, progress)
await InstallPackage(installedPackage.FullPath, torchVersion, progress, onConsoleOutput)
.ConfigureAwait(false);

return new InstalledPackageVersion { InstalledReleaseVersion = latestRelease.TagName };
Expand All @@ -312,7 +312,7 @@ await DownloadPackage(
progress
)
.ConfigureAwait(false);
await InstallPackage(installedPackage.FullPath, torchVersion, progress)
await InstallPackage(installedPackage.FullPath, torchVersion, progress, onConsoleOutput)
.ConfigureAwait(false);

return new InstalledPackageVersion
Expand Down
108 changes: 79 additions & 29 deletions StabilityMatrix.Core/Models/Packages/ComfyUI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
using StabilityMatrix.Core.Processes;
using StabilityMatrix.Core.Python;
using StabilityMatrix.Core.Services;
using YamlDotNet.RepresentationModel;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
using YamlDotNet.Serialization.TypeInspectors;

namespace StabilityMatrix.Core.Models.Packages;

Expand Down Expand Up @@ -233,46 +235,94 @@ SharedFolderMethod sharedFolderMethod
var extraPathsYamlPath = installDirectory + "extra_model_paths.yaml";
var modelsDir = SettingsManager.ModelsDirectory;

var deserializer = new DeserializerBuilder()
.WithNamingConvention(UnderscoredNamingConvention.Instance)
.IgnoreUnmatchedProperties()
.Build();

var exists = File.Exists(extraPathsYamlPath);
if (!exists)
{
Logger.Info("Creating extra_model_paths.yaml");
File.WriteAllText(extraPathsYamlPath, string.Empty);
}
var yaml = File.ReadAllText(extraPathsYamlPath);
var comfyModelPaths =
deserializer.Deserialize<ComfyModelPathsYaml>(yaml)
??
// ReSharper disable once NullCoalescingConditionIsAlwaysNotNullAccordingToAPIContract
// cuz it can actually be null lol
new ComfyModelPathsYaml();

comfyModelPaths.StabilityMatrix ??= new ComfyModelPathsYaml.SmData();
comfyModelPaths.StabilityMatrix.Checkpoints = Path.Combine(modelsDir, "StableDiffusion");
comfyModelPaths.StabilityMatrix.Vae = Path.Combine(modelsDir, "VAE");
comfyModelPaths.StabilityMatrix.Loras =
$"{Path.Combine(modelsDir, "Lora")}\n" + $"{Path.Combine(modelsDir, "LyCORIS")}";
comfyModelPaths.StabilityMatrix.UpscaleModels =
$"{Path.Combine(modelsDir, "ESRGAN")}\n"
+ $"{Path.Combine(modelsDir, "RealESRGAN")}\n"
+ $"{Path.Combine(modelsDir, "SwinIR")}";
comfyModelPaths.StabilityMatrix.Embeddings = Path.Combine(modelsDir, "TextualInversion");
comfyModelPaths.StabilityMatrix.Hypernetworks = Path.Combine(modelsDir, "Hypernetwork");
comfyModelPaths.StabilityMatrix.Controlnet = Path.Combine(modelsDir, "ControlNet");
comfyModelPaths.StabilityMatrix.Clip = Path.Combine(modelsDir, "CLIP");
comfyModelPaths.StabilityMatrix.Diffusers = Path.Combine(modelsDir, "Diffusers");
comfyModelPaths.StabilityMatrix.Gligen = Path.Combine(modelsDir, "GLIGEN");
comfyModelPaths.StabilityMatrix.VaeApprox = Path.Combine(modelsDir, "ApproxVAE");
using var sr = new StringReader(yaml);
var yamlStream = new YamlStream();
yamlStream.Load(sr);

if (!yamlStream.Documents.Any())
{
yamlStream.Documents.Add(new YamlDocument(new YamlMappingNode()));
}

var root = yamlStream.Documents[0].RootNode;
if (root is not YamlMappingNode mappingNode)
{
throw new Exception("Invalid extra_model_paths.yaml");
}
// check if we have a child called "stability_matrix"
var stabilityMatrixNode = mappingNode.Children.FirstOrDefault(
c => c.Key.ToString() == "stability_matrix"
);

if (stabilityMatrixNode.Key != null)
{
if (stabilityMatrixNode.Value is not YamlMappingNode nodeValue)
return Task.CompletedTask;

nodeValue.Children["checkpoints"] = Path.Combine(modelsDir, "StableDiffusion");
nodeValue.Children["vae"] = Path.Combine(modelsDir, "VAE");
nodeValue.Children["loras"] =
$"{Path.Combine(modelsDir, "Lora")}\n" + $"{Path.Combine(modelsDir, "LyCORIS")}";
nodeValue.Children["upscale_models"] =
$"{Path.Combine(modelsDir, "ESRGAN")}\n"
+ $"{Path.Combine(modelsDir, "RealESRGAN")}\n"
+ $"{Path.Combine(modelsDir, "SwinIR")}";
nodeValue.Children["embeddings"] = Path.Combine(modelsDir, "TextualInversion");
nodeValue.Children["hypernetworks"] = Path.Combine(modelsDir, "Hypernetwork");
nodeValue.Children["controlnet"] = Path.Combine(modelsDir, "ControlNet");
nodeValue.Children["clip"] = Path.Combine(modelsDir, "CLIP");
nodeValue.Children["diffusers"] = Path.Combine(modelsDir, "Diffusers");
nodeValue.Children["gligen"] = Path.Combine(modelsDir, "GLIGEN");
nodeValue.Children["vae_approx"] = Path.Combine(modelsDir, "ApproxVAE");
}
else
{
stabilityMatrixNode = new KeyValuePair<YamlNode, YamlNode>(
new YamlScalarNode("stability_matrix"),
new YamlMappingNode
{
{ "checkpoints", Path.Combine(modelsDir, "StableDiffusion") },
{ "vae", Path.Combine(modelsDir, "VAE") },
{
"loras",
$"{Path.Combine(modelsDir, "Lora")}\n{Path.Combine(modelsDir, "LyCORIS")}"
},
{
"upscale_models",
$"{Path.Combine(modelsDir, "ESRGAN")}\n{Path.Combine(modelsDir, "RealESRGAN")}\n{Path.Combine(modelsDir, "SwinIR")}"
},
{ "embeddings", Path.Combine(modelsDir, "TextualInversion") },
{ "hypernetworks", Path.Combine(modelsDir, "Hypernetwork") },
{ "controlnet", Path.Combine(modelsDir, "ControlNet") },
{ "clip", Path.Combine(modelsDir, "CLIP") },
{ "diffusers", Path.Combine(modelsDir, "Diffusers") },
{ "gligen", Path.Combine(modelsDir, "GLIGEN") },
{ "vae_approx", Path.Combine(modelsDir, "ApproxVAE") }
}
);
}

var newRootNode = new YamlMappingNode();
foreach (
var child in mappingNode.Children.Where(c => c.Key.ToString() != "stability_matrix")
)
{
newRootNode.Children.Add(child);
}

newRootNode.Children.Add(stabilityMatrixNode);

var serializer = new SerializerBuilder()
.WithNamingConvention(UnderscoredNamingConvention.Instance)
.Build();
var yamlData = serializer.Serialize(comfyModelPaths);
var yamlData = serializer.Serialize(newRootNode);
File.WriteAllText(extraPathsYamlPath, yamlData);

return Task.CompletedTask;
Expand Down
Loading
Loading