Skip to content

Commit 387c7b9

Browse files
authored
Merge pull request #1547 from LykosAI/main
v2.15.6
2 parents a17eb18 + 9ee3ce0 commit 387c7b9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+2116
-433
lines changed

CHANGELOG.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,40 @@ All notable changes to Stability Matrix will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2.0.0.html).
77

8+
## v2.15.6
9+
### Added
10+
- Added NVIDIA driver version warning when launching ComfyUI with CUDA 13.0 (cu130) and driver versions below 580.x
11+
- Added legacy Python warning when launching InvokeAI installations using Python 3.10.11
12+
- Added Tiled VAE Decode to the Inference video workflows - thanks to @NeuralFault!
13+
### Changed
14+
- Disabled update checking for legacy InvokeAI installations using Python 3.10.11
15+
- Hide rating stars in the Civitai browser page if no rating is available
16+
- Updated uv to v0.9.30
17+
- Updated PortableGit to v2.52.0.windows.1
18+
- Updated Sage/Triton/Nunchaku installers to use GitHub API to fetch latest releases
19+
- Updated ComfyUI installations and updates to automatically install ComfyUI Manager
20+
- Updated gfx110X Windows ROCm nightly index - thanks to @NeuralFault!
21+
- Updated ComfyUI-Zluda install to more closely match the author's intended installation method - thanks to @NeuralFault!
22+
- Updated Forge Classic installs/updates to use the upstream install script for better version compatibility with torch/sage/triton/nunchaku
23+
- Backslashes can now be escaped in Inference prompts via `\\`
24+
### Fixed
25+
- Fixed parsing of escape sequences in Inference such as `\\`
26+
- Fixed [#1546](https://github.com/LykosAI/StabilityMatrix/issues/1546), [#1541](https://github.com/LykosAI/StabilityMatrix/issues/1541) - "No module named 'pkg_resources'" error when installing Automatic1111/Forge/reForge packages
27+
- Fixed [#1545](https://github.com/LykosAI/StabilityMatrix/issues/1545), [#1518](https://github.com/LykosAI/StabilityMatrix/issues/1518), [#1513](https://github.com/LykosAI/StabilityMatrix/issues/1513), [#1488](https://github.com/LykosAI/StabilityMatrix/issues/1488) - Forge Neo update breaking things
28+
- Fixed [#1529](https://github.com/LykosAI/StabilityMatrix/issues/1529) - "Selected commit is null" error when installing packages and rate limited by GitHub
29+
- Fixed [#1525](https://github.com/LykosAI/StabilityMatrix/issues/1525) - Crash after downloading a model
30+
- Fixed [#1523](https://github.com/LykosAI/StabilityMatrix/issues/1523), [#1499](https://github.com/LykosAI/StabilityMatrix/issues/1499), [#1494](https://github.com/LykosAI/StabilityMatrix/issues/1494) - Automatic1111 using old stable diffusion repo
31+
- Fixed [#1505](https://github.com/LykosAI/StabilityMatrix/issues/1505) - incorrect port argument for Wan2GP
32+
- Possibly fix [#1502](https://github.com/LykosAI/StabilityMatrix/issues/1502) - English fonts not displaying correctly on Linux in Chinese environments
33+
- Fixed [#1476](https://github.com/LykosAI/StabilityMatrix/issues/1476) - Incorrect shared output folder for Forge Classic/Neo
34+
- Fixed [#1466](https://github.com/LykosAI/StabilityMatrix/issues/1466) - crash after moving portable install
35+
- Fixed [#1445](https://github.com/LykosAI/StabilityMatrix/issues/1445) - Linux app updates not actually updating - thanks to @NeuralFault!
36+
### Supporters
37+
#### 🌟 Visionaries
38+
To our stellar Visionaries: **Waterclouds**, **JungleDragon**, **bluepopsicle**, **Bob S**, and **whudunit**! Your generosity keeps this project thriving and gives us the confidence to tackle the big challenges. Thank you for being the foundation that makes it all possible!
39+
#### 🚀 Pioneers
40+
Shoutout to our incredible Pioneer crew for keeping the momentum going! Thank you to: **Szir777**, **Noah M**, **[USA]TechDude**, **Thom**, **SeraphOfSalem**, **Desert Viber**, **Adam**, **Droolguy**, **ACTUALLY_the_Real_Willem_Dafoe**, **takyamtom**, **robek**, **Ghislain G**, **Phil R**, **Tundra Everquill**, and a warm welcome to our newest Pioneers: **Andrew B**, **snotty**, **Miguel A**, **SinthCore**, and **Ahmed S**!
41+
842
## v2.15.5
943
### Added
1044
- Added new package - [Wan2GP](https://github.com/deepbeepmeep/Wan2GP)

StabilityMatrix.Avalonia/App.axaml.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,28 @@ public FontFamily GetPlatformDefaultFontFamily()
250250
fonts.Add("Helvetica Neue");
251251
fonts.Add("Helvetica");
252252
}
253+
else if (Compat.IsLinux)
254+
{
255+
// For Chinese locales, prioritize CJK-capable fonts first
256+
if (Cultures.Current?.Name is "zh-Hans" or "zh-Hant")
257+
{
258+
// Common Chinese fonts on Linux systems
259+
fonts.Add("Noto Sans CJK SC");
260+
fonts.Add("Noto Sans CJK TC");
261+
fonts.Add("Source Han Sans");
262+
fonts.Add("WenQuanYi Micro Hei");
263+
fonts.Add("WenQuanYi Zen Hei");
264+
}
265+
266+
// Add common Linux fonts
267+
fonts.Add("Ubuntu");
268+
fonts.Add("DejaVu Sans");
269+
270+
// Fallback to system default
271+
fonts.Add(FontFamily.Default.Name);
272+
273+
return new FontFamily(string.Join(",", fonts));
274+
}
253275
else
254276
{
255277
return FontFamily.Default;
@@ -281,6 +303,9 @@ private void Setup()
281303
Logger.Debug("ActivatableLifetime available, setting up activation protocol handlers");
282304
activatableLifetime.Activated += OnActivated;
283305
}
306+
307+
// Update font when culture/language changes
308+
EventManager.Instance.CultureChanged += (_, _) => SetFontFamily(GetPlatformDefaultFontFamily());
284309
}
285310

286311
private void ShowMainWindow()

StabilityMatrix.Avalonia/Assets/ImagePrompt.tmLanguage.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"name": "constant.character.escape.prompt"
2727
}
2828
},
29-
"end": "[-+.!(){}\\[\\]<\\>:]",
29+
"end": "[-+.!(){}\\[\\]<\\>:|\\\\]",
3030
"endCaptures": {
3131
"0": {
3232
"name": "constant.character.escape.target.prompt"
@@ -35,7 +35,7 @@
3535
"name": "meta.structure.escape.prompt",
3636
"patterns": [
3737
{
38-
"match": "[^-+.!(){}\\[\\]<\\>:]",
38+
"match": "[^-+.!(){}\\[\\]<\\>:|\\\\]",
3939
"name": "invalid.illegal.escape.prompt"
4040
}
4141
]
@@ -147,7 +147,7 @@
147147
"4": {
148148
"name": "punctuation.separator.variable.prompt"
149149
},
150-
"5" : {
150+
"5": {
151151
"name": "constant.numeric"
152152
}
153153
}
@@ -214,7 +214,7 @@
214214
"match": "[^#,:\\[\\]\\(\\)\\<\\> \\\\]+",
215215
"name": "meta.embedded"
216216
},
217-
"invalid_reserved" : {
217+
"invalid_reserved": {
218218
"name": "invalid.illegal.reserved.prompt",
219219
"patterns": [
220220
{

StabilityMatrix.Avalonia/DesignData/MockLaunchPageViewModel.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,13 @@ IServiceManager<ViewModelBase> dialogFactory
3636
public override BasePackage? SelectedBasePackage =>
3737
SelectedPackage?.PackageName != "dank-diffusion"
3838
? base.SelectedBasePackage
39-
: new DankDiffusion(null!, null!, null!, null!, null!);
39+
: new DankDiffusion(null!, null!, null!, null!, null!, null!);
4040

4141
protected override Task LaunchImpl(string? command)
4242
{
4343
IsLaunchTeachingTipsOpen = false;
4444

45-
RunningPackage = new PackagePair(null!, new DankDiffusion(null!, null!, null!, null!, null!));
45+
RunningPackage = new PackagePair(null!, new DankDiffusion(null!, null!, null!, null!, null!, null!));
4646

4747
Console.Document.Insert(
4848
0,

StabilityMatrix.Avalonia/Helpers/UnixPrerequisiteHelper.cs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ IPyInstallationManager pyInstallationManager
3535
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
3636

3737
private const string UvMacDownloadUrl =
38-
"https://github.com/astral-sh/uv/releases/download/0.8.4/uv-aarch64-apple-darwin.tar.gz";
38+
"https://github.com/astral-sh/uv/releases/download/0.9.30/uv-aarch64-apple-darwin.tar.gz";
3939
private const string UvLinuxDownloadUrl =
40-
"https://github.com/astral-sh/uv/releases/download/0.8.4/uv-x86_64-unknown-linux-gnu.tar.gz";
40+
"https://github.com/astral-sh/uv/releases/download/0.9.30/uv-x86_64-unknown-linux-gnu.tar.gz";
4141

4242
private DirectoryPath HomeDir => settingsManager.LibraryDir;
4343
private DirectoryPath AssetsDir => HomeDir.JoinDir("Assets");
@@ -75,7 +75,7 @@ private bool IsPythonVersionInstalled(PyVersion version) =>
7575
// Cached store of whether or not git is installed
7676
private bool? isGitInstalled;
7777

78-
private string ExpectedUvVersion => "0.8.4";
78+
private string ExpectedUvVersion => "0.9.30";
7979

8080
public bool IsVcBuildToolsInstalled => false;
8181
public bool IsHipSdkInstalled => false;
@@ -272,7 +272,13 @@ private async Task RunGit(ProcessArgs args, string? workingDirectory = null)
272272
var result = await ProcessRunner.RunBashCommand(
273273
command,
274274
workingDirectory ?? string.Empty,
275-
new Dictionary<string, string> { { "GIT_TERMINAL_PROMPT", "0" } }
275+
new Dictionary<string, string>
276+
{
277+
{ "GIT_TERMINAL_PROMPT", "0" },
278+
// Set UTF-8 locale to handle Unicode characters in paths
279+
{ "LC_ALL", "C.UTF-8" },
280+
{ "LANG", "C.UTF-8" },
281+
}
276282
);
277283
if (result.ExitCode != 0)
278284
{
@@ -375,7 +381,16 @@ public async Task InstallPythonIfNecessary(PyVersion version, IProgress<Progress
375381

376382
public Task<ProcessResult> GetGitOutput(ProcessArgs args, string? workingDirectory = null)
377383
{
378-
return ProcessRunner.RunBashCommand(args.Prepend("git"), workingDirectory ?? "");
384+
return ProcessRunner.RunBashCommand(
385+
args.Prepend("git"),
386+
workingDirectory ?? "",
387+
new Dictionary<string, string>
388+
{
389+
// Set UTF-8 locale to handle Unicode characters in paths
390+
{ "LC_ALL", "C.UTF-8" },
391+
{ "LANG", "C.UTF-8" },
392+
}
393+
);
379394
}
380395

381396
private async Task<string> RunNode(

StabilityMatrix.Avalonia/Helpers/WindowsPrerequisiteHelper.cs

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ IPyInstallationManager pyInstallationManager
2727
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
2828

2929
private const string PortableGitDownloadUrl =
30-
"https://github.com/git-for-windows/git/releases/download/v2.41.0.windows.1/PortableGit-2.41.0-64-bit.7z.exe";
30+
"https://github.com/git-for-windows/git/releases/download/v2.52.0.windows.1/PortableGit-2.52.0-64-bit.7z.exe";
31+
private const string ExpectedGitVersion = "2.52.0";
3132

3233
private const string VcRedistDownloadUrl = "https://aka.ms/vs/16/release/vc_redist.x64.exe";
3334

@@ -49,7 +50,7 @@ IPyInstallationManager pyInstallationManager
4950
private const string PythonLibsDownloadUrl = "https://cdn.lykos.ai/python_libs_for_sage.zip";
5051

5152
private const string UvWindowsDownloadUrl =
52-
"https://github.com/astral-sh/uv/releases/download/0.8.4/uv-x86_64-pc-windows-msvc.zip";
53+
"https://github.com/astral-sh/uv/releases/download/0.9.30/uv-x86_64-pc-windows-msvc.zip";
5354

5455
private string HomeDir => settingsManager.LibraryDir;
5556

@@ -115,7 +116,7 @@ private string GetPythonLibraryZipPath(PyVersion version) =>
115116
private string UvExtractPath => Path.Combine(AssetsDir, "uv");
116117
public string UvExePath => Path.Combine(UvExtractPath, "uv.exe");
117118
public bool IsUvInstalled => File.Exists(UvExePath);
118-
private string ExpectedUvVersion => "0.8.4";
119+
private string ExpectedUvVersion => "0.9.30";
119120

120121
public string GitBinPath => Path.Combine(PortableGitInstallDir, "bin");
121122
public bool IsVcBuildToolsInstalled => Directory.Exists(VcBuildToolsExistsPath);
@@ -155,6 +156,10 @@ public async Task RunGit(
155156
{
156157
{ "PATH", Compat.GetEnvPathWithExtensions(GitBinPath) },
157158
{ "GIT_TERMINAL_PROMPT", "0" },
159+
// Set UTF-8 locale to handle Unicode characters in paths
160+
// This helps Git load libcurl-4.dll when paths contain non-ASCII characters
161+
{ "LC_ALL", "C.UTF-8" },
162+
{ "LANG", "C.UTF-8" },
158163
}
159164
);
160165
await process.WaitForExitAsync().ConfigureAwait(false);
@@ -173,6 +178,10 @@ public Task<ProcessResult> GetGitOutput(ProcessArgs args, string? workingDirecto
173178
environmentVariables: new Dictionary<string, string>
174179
{
175180
{ "PATH", Compat.GetEnvPathWithExtensions(GitBinPath) },
181+
// Set UTF-8 locale to handle Unicode characters in paths
182+
// This helps Git load libcurl-4.dll when paths contain non-ASCII characters
183+
{ "LC_ALL", "C.UTF-8" },
184+
{ "LANG", "C.UTF-8" },
176185
}
177186
);
178187
}
@@ -605,11 +614,31 @@ public async Task InstallGitIfNecessary(IProgress<ProgressReport>? progress = nu
605614
{
606615
if (File.Exists(GitExePath))
607616
{
608-
Logger.Debug("Git already installed at {GitExePath}", GitExePath);
609-
return;
617+
var installedVersion = await GetInstalledGitVersionAsync();
618+
if (installedVersion.Contains(ExpectedGitVersion))
619+
{
620+
Logger.Debug(
621+
"Git {Version} already installed at {GitExePath}",
622+
ExpectedGitVersion,
623+
GitExePath
624+
);
625+
return;
626+
}
627+
628+
Logger.Info(
629+
"Git version mismatch. Installed: {Installed}, Expected: {Expected}. Upgrading...",
630+
installedVersion.Trim(),
631+
ExpectedGitVersion
632+
);
633+
634+
// Delete existing installation to upgrade
635+
if (Directory.Exists(PortableGitInstallDir))
636+
{
637+
await new DirectoryPath(PortableGitInstallDir).DeleteAsync(true);
638+
}
610639
}
611640

612-
Logger.Info("Git not found at {GitExePath}, downloading...", GitExePath);
641+
Logger.Info("Git not found or outdated at {GitExePath}, downloading...", GitExePath);
613642

614643
// Download
615644
if (!File.Exists(PortableGitDownloadPath))
@@ -1139,6 +1168,20 @@ private async Task<string> GetInstalledUvVersionAsync()
11391168
}
11401169
}
11411170

1171+
private async Task<string> GetInstalledGitVersionAsync()
1172+
{
1173+
try
1174+
{
1175+
var result = await GetGitOutput(["--version"]);
1176+
return result.StandardOutput ?? string.Empty;
1177+
}
1178+
catch (Exception e)
1179+
{
1180+
Logger.Warn(e, "Failed to get Git version");
1181+
return string.Empty;
1182+
}
1183+
}
1184+
11421185
private async Task<bool> EnsurePythonVersion(PyVersion pyVersion)
11431186
{
11441187
var result = await pyInstallationManager.GetInstallationAsync(pyVersion);

StabilityMatrix.Avalonia/Services/InferenceClientManager.cs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -331,15 +331,22 @@ ICompletionProvider completionProvider
331331
if (!settingsManager.IsLibraryDirSet)
332332
return;
333333

334-
ResetSharedProperties();
335-
336-
if (IsConnected)
334+
// Dispatch to UI thread to prevent race conditions with Avalonia's selection model.
335+
// The ModelIndexChanged event may be raised from a background thread, and modifying
336+
// observable collections from a non-UI thread can cause ArgumentOutOfRangeException
337+
// when the selection model tries to enumerate selected items.
338+
Dispatcher.UIThread.Post(() =>
337339
{
338-
LoadSharedPropertiesAsync()
339-
.SafeFireAndForget(onException: ex =>
340-
logger.LogError(ex, "Error loading shared properties")
341-
);
342-
}
340+
ResetSharedProperties();
341+
342+
if (IsConnected)
343+
{
344+
LoadSharedPropertiesAsync()
345+
.SafeFireAndForget(onException: ex =>
346+
logger.LogError(ex, "Error loading shared properties")
347+
);
348+
}
349+
});
343350
};
344351
}
345352

StabilityMatrix.Avalonia/ViewModels/CheckpointManager/CheckpointFileViewModel.cs

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -321,41 +321,35 @@ private async Task RenameAsync()
321321
[RelayCommand]
322322
private async Task OpenSafetensorMetadataViewer()
323323
{
324-
if (!CheckpointFile.SafetensorMetadataParsed)
324+
if (
325+
!settingsManager.IsLibraryDirSet
326+
|| new DirectoryPath(settingsManager.ModelsDirectory) is not { Exists: true } modelsDir
327+
)
325328
{
326-
if (
327-
!settingsManager.IsLibraryDirSet
328-
|| new DirectoryPath(settingsManager.ModelsDirectory) is not { Exists: true } modelsDir
329-
)
330-
{
331-
return;
332-
}
333-
334-
try
335-
{
336-
var safetensorPath = CheckpointFile.GetFullPath(modelsDir);
337-
338-
var metadata = await SafetensorMetadata.ParseAsync(safetensorPath);
339-
340-
CheckpointFile.SafetensorMetadataParsed = true;
341-
CheckpointFile.SafetensorMetadata = metadata;
342-
}
343-
catch (Exception ex)
344-
{
345-
logger.LogWarning(ex, "Failed to parse safetensor metadata");
346-
return;
347-
}
329+
return;
348330
}
349331

350-
if (!CheckpointFile.SafetensorMetadataParsed)
332+
SafetensorMetadata? metadata;
333+
try
334+
{
335+
var safetensorPath = CheckpointFile.GetFullPath(modelsDir);
336+
metadata = await SafetensorMetadata.ParseAsync(safetensorPath);
337+
}
338+
catch (Exception ex)
351339
{
340+
logger.LogWarning(ex, "Failed to parse safetensor metadata");
341+
notificationService.Show(
342+
"No Metadata Found",
343+
"This safetensor file does not contain any embedded metadata.",
344+
NotificationType.Warning
345+
);
352346
return;
353347
}
354348

355349
var vm = vmFactory.Get<SafetensorMetadataViewModel>(vm =>
356350
{
357351
vm.ModelName = CheckpointFile.DisplayModelName;
358-
vm.Metadata = CheckpointFile.SafetensorMetadata;
352+
vm.Metadata = metadata;
359353
});
360354

361355
var dialog = vm.GetDialog();

0 commit comments

Comments
 (0)