Files
swarm-assistent/AssistentSqliteBootstrap.cs
mrleo1nidandClaude Opus 5 d67f5e396e Add OpenRouter chat provider; fix Windows load errors (0.17.0).
- 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>
2026-09-17 06:18:47 +03:00

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.
}
}
}