Fix installed OBS integration discovery
This commit is contained in:
parent
739e96eee6
commit
eb127eadeb
4
TODO.md
4
TODO.md
@ -50,6 +50,10 @@ Windows installer while preserving the verified in-place updater and DPAPI data.
|
|||||||
It also makes OBS bridge repair recoverable with fresh validation and actionable
|
It also makes OBS bridge repair recoverable with fresh validation and actionable
|
||||||
elevated-process errors, and adds timed permanent device revocation in the WebUI.
|
elevated-process errors, and adds timed permanent device revocation in the WebUI.
|
||||||
|
|
||||||
|
Experimental.8 makes the installed single-file build discover and verify its OBS
|
||||||
|
payload deterministically, adds an executable-level package diagnostic, and shows
|
||||||
|
OBS maintenance failures directly instead of leaving them only in diagnostics.
|
||||||
|
|
||||||
Release-blocking work remains:
|
Release-blocking work remains:
|
||||||
|
|
||||||
- Package the native whisper.cpp worker as the Windows CUDA runtime, then benchmark
|
- Package the native whisper.cpp worker as the Windows CUDA runtime, then benchmark
|
||||||
|
|||||||
@ -22,6 +22,6 @@ companion/scripts/publish-companion.ps1
|
|||||||
|
|
||||||
This verifies both official OBS archives by SHA-256, builds the native module with Visual Studio 2022/CMake, and places the bridge beside the published app as a managed component. In Companion, **Install/Repair** requests Windows administrator approval only to copy that verified component into OBS's shared ProgramData plugin directory. OBS must be closed; Companion refuses plugin maintenance while `obs64.exe` is running.
|
This verifies both official OBS archives by SHA-256, builds the native module with Visual Studio 2022/CMake, and places the bridge beside the published app as a managed component. In Companion, **Install/Repair** requests Windows administrator approval only to copy that verified component into OBS's shared ProgramData plugin directory. OBS must be closed; Companion refuses plugin maintenance while `obs64.exe` is running.
|
||||||
|
|
||||||
Experimental.3 checks for updates after connecting and every six hours. Updates remain user-approved, are checksum-verified, refuse to run while OBS is streaming or recording, replace the installed app and bundled components, then restart Companion. Pairing credentials and settings remain in the per-user data directory. Experimental.7 adds the durable per-user installer; existing portable users install it once, after which updates stay in the stable install directory. Code signing, rollback policy, and target-machine OBS/Twitch acceptance are still required.
|
Experimental.3 checks for updates after connecting and every six hours. Updates remain user-approved, are checksum-verified, refuse to run while OBS is streaming or recording, replace the installed app and bundled components, then restart Companion. Pairing credentials and settings remain in the per-user data directory. Experimental.7 adds the durable per-user installer; existing portable users install it once, after which updates stay in the stable install directory. Experimental.8 fixes packaged OBS integration discovery and exposes a standalone payload diagnostic. Code signing, rollback policy, and target-machine OBS/Twitch acceptance are still required.
|
||||||
|
|
||||||
The Admin **Download Companion** action distributes a private ZIP containing a checksum-pinned Windows x64 installer plus the one-time pairing package. It is intentionally marked experimental and is not code-signed yet.
|
The Admin **Download Companion** action distributes a private ZIP containing a checksum-pinned Windows x64 installer plus the one-time pairing package. It is intentionally marked experimental and is not code-signed yet.
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#ifndef AppVersion
|
#ifndef AppVersion
|
||||||
#define AppVersion "0.1.0-experimental.7"
|
#define AppVersion "0.1.0-experimental.8"
|
||||||
#endif
|
#endif
|
||||||
#ifndef SourceRoot
|
#ifndef SourceRoot
|
||||||
#error SourceRoot must point at the self-contained Companion publish directory.
|
#error SourceRoot must point at the self-contained Companion publish directory.
|
||||||
|
|||||||
@ -94,5 +94,6 @@ $manifest = [ordered]@{
|
|||||||
sha256 = (Get-FileHash $bridgeDll -Algorithm SHA256).Hash.ToLowerInvariant()
|
sha256 = (Get-FileHash $bridgeDll -Algorithm SHA256).Hash.ToLowerInvariant()
|
||||||
obs_minimum_version = "31.0.0"
|
obs_minimum_version = "31.0.0"
|
||||||
}
|
}
|
||||||
$manifest | ConvertTo-Json | Set-Content -Encoding utf8 (Join-Path $componentRoot "manifest.json")
|
$manifestJson = $manifest | ConvertTo-Json
|
||||||
|
[IO.File]::WriteAllText((Join-Path $componentRoot "manifest.json"), $manifestJson, [Text.UTF8Encoding]::new($false))
|
||||||
Write-Host "Built OBS bridge $BridgeVersion at $componentRoot"
|
Write-Host "Built OBS bridge $BridgeVersion at $componentRoot"
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
param(
|
param(
|
||||||
[string]$Version = "0.1.0-experimental.7",
|
[string]$Version = "0.1.0-experimental.8",
|
||||||
[string]$BridgeVersion = "0.1.0-experimental.5"
|
[string]$BridgeVersion = "0.1.0-experimental.5"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -22,6 +22,15 @@ $publishArguments = @("publish", "`"$project`"", "-c", "Release", "-r", "win-x64
|
|||||||
$published = Start-Process -FilePath $dotnet -ArgumentList $publishArguments -NoNewWindow -Wait -PassThru
|
$published = Start-Process -FilePath $dotnet -ArgumentList $publishArguments -NoNewWindow -Wait -PassThru
|
||||||
if ($published.ExitCode) { throw "Companion publish failed." }
|
if ($published.ExitCode) { throw "Companion publish failed." }
|
||||||
|
|
||||||
|
$bridgeDiagnostic = Join-Path $outputRoot "obs-bridge-package-diagnostic.json"
|
||||||
|
Remove-Item $bridgeDiagnostic -Force -ErrorAction SilentlyContinue
|
||||||
|
$diagnosed = Start-Process -FilePath (Join-Path $publishRoot "Lumi.Companion.App.exe") -ArgumentList @("--diagnose-obs-bridge", "`"$bridgeDiagnostic`"") -Wait -PassThru
|
||||||
|
if ($diagnosed.ExitCode -ne 0) {
|
||||||
|
$detail = if (Test-Path $bridgeDiagnostic) { Get-Content $bridgeDiagnostic -Raw } else { "No diagnostic result was written." }
|
||||||
|
throw "Published OBS integration payload failed its executable-level check: $detail"
|
||||||
|
}
|
||||||
|
Remove-Item $bridgeDiagnostic -Force -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
Copy-Item (Join-Path $publishRoot "Lumi.Companion.App.exe") $stageRoot
|
Copy-Item (Join-Path $publishRoot "Lumi.Companion.App.exe") $stageRoot
|
||||||
Copy-Item (Join-Path $publishRoot "components") $stageRoot -Recurse
|
Copy-Item (Join-Path $publishRoot "components") $stageRoot -Recurse
|
||||||
Remove-Item $archive -Force -ErrorAction SilentlyContinue
|
Remove-Item $archive -Force -ErrorAction SilentlyContinue
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||||
<Version>0.1.0-experimental.7</Version>
|
<Version>0.1.0-experimental.8</Version>
|
||||||
<AssemblyVersion>0.1.0.0</AssemblyVersion>
|
<AssemblyVersion>0.1.0.0</AssemblyVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@ -57,7 +57,7 @@ public partial class MainWindow : Window
|
|||||||
SaveSettingsButton.Click += async (_, _) => await SaveSettingsAsync();
|
SaveSettingsButton.Click += async (_, _) => await SaveSettingsAsync();
|
||||||
CheckUpdateButton.Click += async (_, _) => await RunUiActionAsync(() => _runtime.CheckForUpdatesAsync(), CheckUpdateButton);
|
CheckUpdateButton.Click += async (_, _) => await RunUiActionAsync(() => _runtime.CheckForUpdatesAsync(), CheckUpdateButton);
|
||||||
ApplyUpdateButton.Click += async (_, _) => await ApplyUpdateAsync();
|
ApplyUpdateButton.Click += async (_, _) => await ApplyUpdateAsync();
|
||||||
InstallBridgeButton.Click += async (_, _) => await RunUiActionAsync(() => _runtime.InstallOrRepairObsBridgeAsync(), InstallBridgeButton);
|
InstallBridgeButton.Click += async (_, _) => await InstallBridgeAsync();
|
||||||
RemoveBridgeButton.Click += async (_, _) => await RemoveBridgeAsync();
|
RemoveBridgeButton.Click += async (_, _) => await RemoveBridgeAsync();
|
||||||
AdvancedToggle.IsCheckedChanged += (_, _) => AdvancedPanel.IsVisible = AdvancedToggle.IsChecked == true;
|
AdvancedToggle.IsCheckedChanged += (_, _) => AdvancedPanel.IsVisible = AdvancedToggle.IsChecked == true;
|
||||||
SourcePicker.SelectionChanged += async (_, _) =>
|
SourcePicker.SelectionChanged += async (_, _) =>
|
||||||
@ -115,6 +115,21 @@ public partial class MainWindow : Window
|
|||||||
finally { RenderState(_runtime.State); }
|
finally { RenderState(_runtime.State); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task InstallBridgeAsync()
|
||||||
|
{
|
||||||
|
InstallBridgeButton.IsEnabled = false;
|
||||||
|
BridgeStatusText.Text = "Checking the packaged integration and requesting Windows approval…";
|
||||||
|
try { await _runtime.InstallOrRepairObsBridgeAsync(); }
|
||||||
|
catch (Exception error)
|
||||||
|
{
|
||||||
|
AddLog($"{DateTime.Now:HH:mm:ss} {error.Message}");
|
||||||
|
RenderState(_runtime.State);
|
||||||
|
var dialog = new DecisionWindow("OBS integration could not be installed", error.Message, "Close");
|
||||||
|
await dialog.ShowDialog<bool>(this);
|
||||||
|
}
|
||||||
|
finally { RenderState(_runtime.State); }
|
||||||
|
}
|
||||||
|
|
||||||
private async Task SaveSettingsAsync()
|
private async Task SaveSettingsAsync()
|
||||||
{
|
{
|
||||||
SaveSettingsButton.IsEnabled = false;
|
SaveSettingsButton.IsEnabled = false;
|
||||||
|
|||||||
@ -12,6 +12,7 @@ namespace Lumi.Companion.App;
|
|||||||
public sealed class ObsBridgeManager
|
public sealed class ObsBridgeManager
|
||||||
{
|
{
|
||||||
private readonly string _installRoot = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "obs-studio", "plugins", "lumi-obs-bridge");
|
private readonly string _installRoot = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "obs-studio", "plugins", "lumi-obs-bridge");
|
||||||
|
private string? _packageFailure;
|
||||||
private string InstalledDll => Path.Combine(_installRoot, "bin", "64bit", "lumi-obs-bridge.dll");
|
private string InstalledDll => Path.Combine(_installRoot, "bin", "64bit", "lumi-obs-bridge.dll");
|
||||||
private string InstalledManifest => Path.Combine(_installRoot, "lumi-managed.json");
|
private string InstalledManifest => Path.Combine(_installRoot, "lumi-managed.json");
|
||||||
|
|
||||||
@ -24,7 +25,7 @@ public sealed class ObsBridgeManager
|
|||||||
var valid = packageAvailable && fileInstalled && HashFile(InstalledDll) == package!.Manifest.Sha256 && installed?.Version == package.Manifest.Version;
|
var valid = packageAvailable && fileInstalled && HashFile(InstalledDll) == package!.Manifest.Sha256 && installed?.Version == package.Manifest.Version;
|
||||||
return new ObsBridgeStatus(packageAvailable, fileInstalled, valid, package?.Manifest.Version,
|
return new ObsBridgeStatus(packageAvailable, fileInstalled, valid, package?.Manifest.Version,
|
||||||
valid ? $"OBS integration {package!.Manifest.Version} is installed. Restart OBS if it was open during the last repair." :
|
valid ? $"OBS integration {package!.Manifest.Version} is installed. Restart OBS if it was open during the last repair." :
|
||||||
!packageAvailable ? "The bundled OBS integration could not be verified. Use Check now to repair the Companion package." :
|
!packageAvailable ? $"The bundled OBS integration could not be verified. {_packageFailure ?? "The packaged component was not found."}" :
|
||||||
fileInstalled ? "The OBS integration is outdated or damaged. Repair it while OBS is closed." : "The OBS integration is ready to install.");
|
fileInstalled ? "The OBS integration is outdated or damaged. Repair it while OBS is closed." : "The OBS integration is ready to install.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,6 +76,23 @@ public sealed class ObsBridgeManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsMaintenanceRequest(string[] args) => args.Length is 2 or 3 && args[0].Equals("--manage-obs-bridge", StringComparison.OrdinalIgnoreCase);
|
public static bool IsMaintenanceRequest(string[] args) => args.Length is 2 or 3 && args[0].Equals("--manage-obs-bridge", StringComparison.OrdinalIgnoreCase);
|
||||||
|
public static bool IsDiagnosticRequest(string[] args) => args.Length == 2 && args[0].Equals("--diagnose-obs-bridge", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
public static int RunDiagnostic(string[] args)
|
||||||
|
{
|
||||||
|
if (!IsDiagnosticRequest(args)) return 10;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var status = new ObsBridgeManager().Inspect();
|
||||||
|
File.WriteAllBytes(args[1], JsonSerializer.SerializeToUtf8Bytes(status, ProtocolV1.JsonOptions));
|
||||||
|
return status.PackageAvailable ? 0 : 9;
|
||||||
|
}
|
||||||
|
catch (Exception error)
|
||||||
|
{
|
||||||
|
try { File.WriteAllText(args[1], JsonSerializer.Serialize(new { packageAvailable = false, detail = error.Message }, ProtocolV1.JsonOptions)); } catch { }
|
||||||
|
return 9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static int RunMaintenance(string[] args)
|
public static int RunMaintenance(string[] args)
|
||||||
{
|
{
|
||||||
@ -138,33 +156,67 @@ public sealed class ObsBridgeManager
|
|||||||
private static ObsBridgeManifest? ReadManifest(string path) { try { return JsonSerializer.Deserialize<ObsBridgeManifest>(File.ReadAllBytes(path), ProtocolV1.JsonOptions); } catch { return null; } }
|
private static ObsBridgeManifest? ReadManifest(string path) { try { return JsonSerializer.Deserialize<ObsBridgeManifest>(File.ReadAllBytes(path), ProtocolV1.JsonOptions); } catch { return null; } }
|
||||||
private ObsBridgePackage? LoadPackage()
|
private ObsBridgePackage? LoadPackage()
|
||||||
{
|
{
|
||||||
var roots = new[]
|
var failures = new List<string>();
|
||||||
{
|
var roots = CandidatePackageRoots();
|
||||||
Path.Combine(Path.GetDirectoryName(Environment.ProcessPath) ?? string.Empty, "components", "obs-bridge"),
|
|
||||||
Path.Combine(AppContext.BaseDirectory, "components", "obs-bridge")
|
|
||||||
}.Distinct(StringComparer.OrdinalIgnoreCase);
|
|
||||||
foreach (var root in roots)
|
foreach (var root in roots)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var manifestBytes = File.ReadAllBytes(Path.Combine(root, "manifest.json"));
|
var manifestBytes = File.ReadAllBytes(Path.Combine(root, "manifest.json"));
|
||||||
var dll = File.ReadAllBytes(Path.Combine(root, "lumi-obs-bridge.dll"));
|
var dll = File.ReadAllBytes(Path.Combine(root, "lumi-obs-bridge.dll"));
|
||||||
var manifest = JsonSerializer.Deserialize<ObsBridgeManifest>(manifestBytes, ProtocolV1.JsonOptions);
|
var manifest = ParseManifest(manifestBytes);
|
||||||
if (manifest is not null && HashBytes(dll) == manifest.Sha256)
|
var actualHash = HashBytes(dll);
|
||||||
return new ObsBridgePackage(manifest, dll, File.Exists(Path.Combine(root, "en-US.ini")) ? File.ReadAllBytes(Path.Combine(root, "en-US.ini")) : null);
|
if (!actualHash.Equals(manifest.Sha256, StringComparison.OrdinalIgnoreCase))
|
||||||
|
throw new InvalidDataException($"OBS bridge checksum mismatch (expected {manifest.Sha256}, got {actualHash}).");
|
||||||
|
_packageFailure = null;
|
||||||
|
return new ObsBridgePackage(manifest, dll, File.Exists(Path.Combine(root, "en-US.ini")) ? File.ReadAllBytes(Path.Combine(root, "en-US.ini")) : null);
|
||||||
}
|
}
|
||||||
catch { }
|
catch (Exception error) { failures.Add($"{root}: {error.Message}"); }
|
||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var assembly = Assembly.GetExecutingAssembly();
|
var assembly = Assembly.GetExecutingAssembly();
|
||||||
var manifestBytes = ReadResource(assembly, "Lumi.Companion.ObsBridge.manifest.json");
|
var manifestBytes = ReadResource(assembly, "Lumi.Companion.ObsBridge.manifest.json");
|
||||||
var dll = ReadResource(assembly, "Lumi.Companion.ObsBridge.dll");
|
var dll = ReadResource(assembly, "Lumi.Companion.ObsBridge.dll");
|
||||||
var manifest = JsonSerializer.Deserialize<ObsBridgeManifest>(manifestBytes, ProtocolV1.JsonOptions);
|
var manifest = ParseManifest(manifestBytes);
|
||||||
return manifest is not null && HashBytes(dll) == manifest.Sha256
|
var actualHash = HashBytes(dll);
|
||||||
? new ObsBridgePackage(manifest, dll, TryReadResource(assembly, "Lumi.Companion.ObsBridge.en-US.ini")) : null;
|
if (!actualHash.Equals(manifest.Sha256, StringComparison.OrdinalIgnoreCase))
|
||||||
|
throw new InvalidDataException($"Embedded OBS bridge checksum mismatch (expected {manifest.Sha256}, got {actualHash}).");
|
||||||
|
_packageFailure = null;
|
||||||
|
return new ObsBridgePackage(manifest, dll, TryReadResource(assembly, "Lumi.Companion.ObsBridge.en-US.ini"));
|
||||||
}
|
}
|
||||||
catch { return null; }
|
catch (Exception error)
|
||||||
|
{
|
||||||
|
failures.Add($"embedded payload: {error.Message}");
|
||||||
|
_packageFailure = string.Join(" ", failures);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static IReadOnlyList<string> CandidatePackageRoots()
|
||||||
|
{
|
||||||
|
var bases = new List<string?>
|
||||||
|
{
|
||||||
|
Path.GetDirectoryName(Environment.ProcessPath),
|
||||||
|
AppContext.BaseDirectory,
|
||||||
|
Path.GetDirectoryName(Environment.GetCommandLineArgs().FirstOrDefault()),
|
||||||
|
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Programs", "Lumi Companion")
|
||||||
|
};
|
||||||
|
try { bases.Add(Path.GetDirectoryName(Process.GetCurrentProcess().MainModule?.FileName)); } catch { }
|
||||||
|
return bases.Where(value => !string.IsNullOrWhiteSpace(value))
|
||||||
|
.Select(value => Path.Combine(value!, "components", "obs-bridge"))
|
||||||
|
.Distinct(StringComparer.OrdinalIgnoreCase).ToArray();
|
||||||
|
}
|
||||||
|
private static ObsBridgeManifest ParseManifest(byte[] value)
|
||||||
|
{
|
||||||
|
var start = value.Length >= 3 && value[0] == 0xEF && value[1] == 0xBB && value[2] == 0xBF ? 3 : 0;
|
||||||
|
using var document = JsonDocument.Parse(value.AsMemory(start));
|
||||||
|
var root = document.RootElement;
|
||||||
|
var version = root.GetProperty("version").GetString();
|
||||||
|
var sha256 = root.GetProperty("sha256").GetString();
|
||||||
|
var minimum = root.GetProperty("obs_minimum_version").GetString();
|
||||||
|
if (string.IsNullOrWhiteSpace(version) || string.IsNullOrWhiteSpace(minimum) || sha256 is null || sha256.Length != 64 || !sha256.All(Uri.IsHexDigit))
|
||||||
|
throw new InvalidDataException("The OBS bridge manifest is invalid.");
|
||||||
|
return new ObsBridgeManifest(version, sha256.ToLowerInvariant(), minimum);
|
||||||
}
|
}
|
||||||
private static byte[] ReadResource(Assembly assembly, string name) { using var stream = assembly.GetManifestResourceStream(name) ?? throw new FileNotFoundException($"Embedded resource {name} is missing."); using var body = new MemoryStream(); stream.CopyTo(body); return body.ToArray(); }
|
private static byte[] ReadResource(Assembly assembly, string name) { using var stream = assembly.GetManifestResourceStream(name) ?? throw new FileNotFoundException($"Embedded resource {name} is missing."); using var body = new MemoryStream(); stream.CopyTo(body); return body.ToArray(); }
|
||||||
private static byte[]? TryReadResource(Assembly assembly, string name) { try { return ReadResource(assembly, name); } catch { return null; } }
|
private static byte[]? TryReadResource(Assembly assembly, string name) { try { return ReadResource(assembly, name); } catch { return null; } }
|
||||||
|
|||||||
@ -17,6 +17,7 @@ internal static class Program
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (UpdateApplier.IsApplyRequest(args)) return UpdateApplier.Apply(args);
|
if (UpdateApplier.IsApplyRequest(args)) return UpdateApplier.Apply(args);
|
||||||
|
if (ObsBridgeManager.IsDiagnosticRequest(args)) return ObsBridgeManager.RunDiagnostic(args);
|
||||||
if (ObsBridgeManager.IsMaintenanceRequest(args)) return ObsBridgeManager.RunMaintenance(args);
|
if (ObsBridgeManager.IsMaintenanceRequest(args)) return ObsBridgeManager.RunMaintenance(args);
|
||||||
|
|
||||||
LaunchInBackground = args.Contains("--background", StringComparer.OrdinalIgnoreCase);
|
LaunchInBackground = args.Contains("--background", StringComparer.OrdinalIgnoreCase);
|
||||||
|
|||||||
@ -1,17 +1,17 @@
|
|||||||
{
|
{
|
||||||
"schema_version": 1,
|
"schema_version": 1,
|
||||||
"version": "0.1.0-experimental.7",
|
"version": "0.1.0-experimental.8",
|
||||||
"signed": false,
|
"signed": false,
|
||||||
"release_notes": "Adds a durable per-user Windows installer, recoverable OBS integration repair with detailed errors, and permanent device revocation through Lumi's timed confirmation flow.",
|
"release_notes": "Fixes OBS integration package discovery in the installed single-file app, validates the packaged payload directly, and displays actionable installation errors.",
|
||||||
"installer": {
|
"installer": {
|
||||||
"id": "windows-x64-installer",
|
"id": "windows-x64-installer",
|
||||||
"platform": "win32",
|
"platform": "win32",
|
||||||
"architecture": "x64",
|
"architecture": "x64",
|
||||||
"label": "Windows x64 per-user installer",
|
"label": "Windows x64 per-user installer",
|
||||||
"filename": "Lumi.Companion-Setup.exe",
|
"filename": "Lumi.Companion-Setup.exe",
|
||||||
"url": "https://git.rolfsvaag.no/Rolfsvaag_Datateknikk/Lumi/releases/download/companion-v0.1.0-experimental.7/Lumi.Companion-Setup.exe",
|
"url": "https://git.rolfsvaag.no/Rolfsvaag_Datateknikk/Lumi/releases/download/companion-v0.1.0-experimental.8/Lumi.Companion-Setup.exe",
|
||||||
"sha256": "a06319ecbda2369e0f756fb4429d95583a58a1c802ae3537cd44faf0032c3ded",
|
"sha256": "075fb4dd9a84ab10655d75899a6b4944269c9fe6371573778740d80b16ca19d0",
|
||||||
"bytes": 32037289
|
"bytes": 32041200
|
||||||
},
|
},
|
||||||
"artifacts": [
|
"artifacts": [
|
||||||
{
|
{
|
||||||
@ -20,9 +20,9 @@
|
|||||||
"architecture": "x64",
|
"architecture": "x64",
|
||||||
"label": "Windows x64 self-contained",
|
"label": "Windows x64 self-contained",
|
||||||
"filename": "Lumi.Companion-win-x64.zip",
|
"filename": "Lumi.Companion-win-x64.zip",
|
||||||
"url": "https://git.rolfsvaag.no/Rolfsvaag_Datateknikk/Lumi/releases/download/companion-v0.1.0-experimental.7/Lumi.Companion-win-x64.zip",
|
"url": "https://git.rolfsvaag.no/Rolfsvaag_Datateknikk/Lumi/releases/download/companion-v0.1.0-experimental.8/Lumi.Companion-win-x64.zip",
|
||||||
"sha256": "5578b61aafbcf40b84cfa846aa31f2e2ff49700f62692e00c8d0587eac0cb414",
|
"sha256": "46c58b044a213e328fa96fe86e48b9ea0b67e327439fed14fc485c711f03eb3e",
|
||||||
"bytes": 41757402,
|
"bytes": 41757425,
|
||||||
"entrypoint": "Lumi.Companion.App.exe"
|
"entrypoint": "Lumi.Companion.App.exe"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"id": "lumi_transcription",
|
"id": "lumi_transcription",
|
||||||
"name": "Lumi Transcription",
|
"name": "Lumi Transcription",
|
||||||
"version": "0.1.0-experimental.7",
|
"version": "0.1.0-experimental.8",
|
||||||
"description": "Server-hosted whisper.cpp transcription for Lumi Companion and OBS closed captions.",
|
"description": "Server-hosted whisper.cpp transcription for Lumi Companion and OBS closed captions.",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"channel": "experimental",
|
"channel": "experimental",
|
||||||
|
|||||||
@ -117,6 +117,7 @@ function verifyLocalhostTransportPolicy() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function verifyCompanionVersionOrdering() {
|
function verifyCompanionVersionOrdering() {
|
||||||
|
assert.equal(plugin.compareVersions("0.1.0-experimental.8", "0.1.0-experimental.7"), 1);
|
||||||
assert.equal(plugin.compareVersions("0.1.0-experimental.7", "0.1.0-experimental.6"), 1);
|
assert.equal(plugin.compareVersions("0.1.0-experimental.7", "0.1.0-experimental.6"), 1);
|
||||||
assert.equal(plugin.compareVersions("0.1.0-experimental.6", "0.1.0-experimental.5"), 1);
|
assert.equal(plugin.compareVersions("0.1.0-experimental.6", "0.1.0-experimental.5"), 1);
|
||||||
assert.equal(plugin.compareVersions("0.1.0-experimental.5", "0.1.0-experimental.4"), 1);
|
assert.equal(plugin.compareVersions("0.1.0-experimental.5", "0.1.0-experimental.4"), 1);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user