Merge pull request #1561 from segmentationf4u1t/fix/windows-segfault-minimal

fix: prevent Windows ORT preload crash
This commit is contained in:
Can Bölük
2026-05-31 04:45:02 +03:00
committed by GitHub
5 changed files with 22 additions and 8 deletions
+2
View File
@@ -103,6 +103,7 @@
"dependencies": {
"@oh-my-pi/pi-ai": "catalog:",
"fastembed": "catalog:",
"onnxruntime-node": "catalog:",
},
"devDependencies": {
"@types/bun": "catalog:",
@@ -278,6 +279,7 @@
"lucide-react": "^1.16.0",
"marked": "^18.0.4",
"markit-ai": "0.5.3",
"onnxruntime-node": "1.24.3",
"openai": "^6.39.0",
"partial-json": "^0.1.7",
"postcss": "^8.5.15",
+1
View File
@@ -58,6 +58,7 @@
"lucide-react": "^1.16.0",
"marked": "^18.0.4",
"markit-ai": "0.5.3",
"onnxruntime-node": "1.24.3",
"openai": "^6.39.0",
"partial-json": "^0.1.7",
"postcss": "^8.5.15",
+1
View File
@@ -4,6 +4,7 @@
### Fixed
- Fixed Windows startup crashes by keeping fastembed's older ONNX Runtime binding lazy until local embeddings are used.
- Fixed a segfault at startup from eagerly loading fastembed: importing the embeddings module pulled in `fastembed`, which eagerly loads the `onnxruntime-node` native addon. The import is now deferred until a local fastembed model is actually initialized, so API-model, disabled-embeddings, and test runtimes never load the native addon.
## [15.6.0] - 2026-05-30
+2 -1
View File
@@ -40,7 +40,8 @@
},
"dependencies": {
"@oh-my-pi/pi-ai": "catalog:",
"fastembed": "catalog:"
"fastembed": "catalog:",
"onnxruntime-node": "catalog:"
},
"devDependencies": {
"@types/bun": "catalog:"
+16 -7
View File
@@ -1,5 +1,6 @@
import { mkdirSync } from "node:fs";
import type { EmbeddingModel } from "fastembed";
import { createRequire } from "node:module";
import type { EmbeddingModel, FlagEmbedding } from "fastembed";
import { getMnemosyneRuntimeOptions, resolveEmbeddingProvider } from "./runtime-options";
export type Vector = number[];
@@ -24,8 +25,14 @@ type LocalModelInitOptions = {
};
type LocalModelInitializer = (options: LocalModelInitOptions) => Promise<LocalEmbeddingModel>;
interface FastembedRuntime {
EmbeddingModel: typeof EmbeddingModel;
FlagEmbedding: typeof FlagEmbedding;
}
const FASTEMBED_CACHE_DIR = `${process.env.HOME ?? ""}/.hermes/cache/fastembed`;
const QUERY_CACHE_MAX = 512;
const sourceRequire = createRequire(import.meta.url);
let providerOverride: EmbeddingProvider | null = null;
let localModelPromise: Promise<LocalEmbeddingModel> | null = null;
@@ -33,12 +40,14 @@ let localModelInitializer: LocalModelInitializer = defaultLocalModelInitializer;
let apiCallCount = 0;
const queryCache = new Map<string, Vector>();
async function defaultLocalModelInitializer(options: LocalModelInitOptions): Promise<LocalEmbeddingModel> {
// Lazily pull in fastembed here — its module eagerly imports `onnxruntime-node`,
// whose native addon load segfaults in some runtimes. Deferring to the actual
// model init keeps API-model, disabled, and test runtimes from ever loading it.
const { FlagEmbedding } = await import("fastembed");
return FlagEmbedding.init(options) as Promise<LocalEmbeddingModel>;
function loadFastembedRuntime(): FastembedRuntime {
// Preload ORT 1.24 before fastembed's ORT 1.21 binding to avoid Windows DLL reuse crashes.
sourceRequire("onnxruntime-node");
return sourceRequire("fastembed") as FastembedRuntime;
}
function defaultLocalModelInitializer(options: LocalModelInitOptions): Promise<LocalEmbeddingModel> {
return loadFastembedRuntime().FlagEmbedding.init(options);
}
function activeEmbeddingOptions() {