- OpenRouter as an alternative chat provider: server-side API key (settings.json or OPENROUTER_API_KEY), model list with vision marks and filter, SSE streaming, images as data URLs. Memory embeddings stay on Ollama; park/warm LLM are no-ops for the remote provider. - AssistentSaveKnowledgeAttach: JArray param is not supported by SwarmUI API reflection and aborted registration of every later API call; use string[]. - SQLite bootstrap: preload native e_sqlite3 for the current OS/arch (win/osx/linux) and resolve DllImport to it. - settings.json: shared-read + atomic write with retry to avoid Windows sharing violations. - csproj: fix MSB4012 in the native SQLite copy target. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
99 lines
3.3 KiB
C#
99 lines
3.3 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Runtime.InteropServices;
|
|
using System.Threading;
|
|
using SQLitePCL;
|
|
|
|
namespace Mrleo1nid.SwarmAssistent;
|
|
|
|
/// <summary>
|
|
/// SwarmUI loads extensions in an isolated AssemblyLoadContext — Microsoft.Data.Sqlite
|
|
/// does not auto-init native SQLite there. Native libs ship under the extension dir
|
|
/// (runtimes/linux-x64/native/libe_sqlite3.so), but the loader searches the host
|
|
/// base dir unless we preload from the extension assembly location.
|
|
/// </summary>
|
|
internal static class AssistentSqliteBootstrap
|
|
{
|
|
static int _ready;
|
|
|
|
internal static void EnsureInitialized()
|
|
{
|
|
if (Interlocked.CompareExchange(ref _ready, 1, 0) != 0)
|
|
{
|
|
return;
|
|
}
|
|
PreloadNativeLibrary();
|
|
Batteries_V2.Init();
|
|
}
|
|
|
|
static void PreloadNativeLibrary()
|
|
{
|
|
string extDir = Path.GetDirectoryName(typeof(AssistentSqliteBootstrap).Assembly.Location)
|
|
?? AppContext.BaseDirectory
|
|
?? "";
|
|
if (string.IsNullOrWhiteSpace(extDir))
|
|
{
|
|
return;
|
|
}
|
|
foreach (string rel in CandidatePaths())
|
|
{
|
|
string path = Path.Combine(extDir, rel);
|
|
if (!File.Exists(path))
|
|
{
|
|
continue;
|
|
}
|
|
try
|
|
{
|
|
IntPtr handle = NativeLibrary.Load(path);
|
|
RegisterResolver(handle);
|
|
return;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SwarmUI.Utils.Logs.Debug($"AssistentSqliteBootstrap: NativeLibrary.Load({path}): {ex.Message}");
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>Native e_sqlite3 locations for the current OS / arch, most specific first.</summary>
|
|
static string[] CandidatePaths()
|
|
{
|
|
string arch = RuntimeInformation.ProcessArchitecture switch
|
|
{
|
|
Architecture.Arm64 => "arm64",
|
|
Architecture.X86 => "x86",
|
|
Architecture.Arm => "arm",
|
|
_ => "x64",
|
|
};
|
|
if (OperatingSystem.IsWindows())
|
|
{
|
|
return [Path.Combine("runtimes", $"win-{arch}", "native", "e_sqlite3.dll"), "e_sqlite3.dll"];
|
|
}
|
|
if (OperatingSystem.IsMacOS())
|
|
{
|
|
return [Path.Combine("runtimes", $"osx-{arch}", "native", "libe_sqlite3.dylib"), "libe_sqlite3.dylib"];
|
|
}
|
|
return
|
|
[
|
|
Path.Combine("runtimes", $"linux-{arch}", "native", "libe_sqlite3.so"),
|
|
Path.Combine("runtimes", $"linux-{arch}", "native", "e_sqlite3.so"),
|
|
"libe_sqlite3.so",
|
|
"e_sqlite3.so",
|
|
];
|
|
}
|
|
|
|
/// <summary>The provider's [DllImport("e_sqlite3")] would otherwise probe the host dir, not the extension dir.</summary>
|
|
static void RegisterResolver(IntPtr handle)
|
|
{
|
|
try
|
|
{
|
|
NativeLibrary.SetDllImportResolver(typeof(SQLite3Provider_e_sqlite3).Assembly,
|
|
(name, _, _) => name.Contains("e_sqlite3", StringComparison.OrdinalIgnoreCase) ? handle : IntPtr.Zero);
|
|
}
|
|
catch (InvalidOperationException)
|
|
{
|
|
// A resolver is already set for this assembly — the preloaded handle still helps on Windows.
|
|
}
|
|
}
|
|
}
|