Skip to content

Commit

Permalink
Merge pull request #135 from LykosAI/main
Browse files Browse the repository at this point in the history
  • Loading branch information
ionite34 authored Sep 18, 2023
2 parents 2d0965a + 1cecdf9 commit 64180c0
Show file tree
Hide file tree
Showing 13 changed files with 193 additions and 53 deletions.
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

0 comments on commit 64180c0

Please sign in to comment.