@reftrixmcp/ml 0.3.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/worker-resource-limits.d.ts +89 -0
- package/dist/config/worker-resource-limits.d.ts.map +1 -0
- package/dist/config/worker-resource-limits.js +156 -0
- package/dist/config/worker-resource-limits.js.map +1 -0
- package/dist/dinov2/service.d.ts.map +1 -1
- package/dist/dinov2/service.js +70 -10
- package/dist/dinov2/service.js.map +1 -1
- package/dist/dinov2/worker-thread.js +72 -9
- package/dist/dinov2/worker-thread.js.map +1 -1
- package/dist/embeddings/service.d.ts.map +1 -1
- package/dist/embeddings/service.js +13 -1
- package/dist/embeddings/service.js.map +1 -1
- package/dist/embeddings/worker-thread.d.ts.map +1 -1
- package/dist/embeddings/worker-thread.js +8 -83
- package/dist/embeddings/worker-thread.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/onnx-availability.d.ts +29 -0
- package/dist/onnx-availability.d.ts.map +1 -0
- package/dist/onnx-availability.js +69 -0
- package/dist/onnx-availability.js.map +1 -0
- package/dist/onnx-provider-detect.d.ts +47 -0
- package/dist/onnx-provider-detect.d.ts.map +1 -0
- package/dist/onnx-provider-detect.js +111 -0
- package/dist/onnx-provider-detect.js.map +1 -0
- package/package.json +5 -3
- package/src/config/worker-resource-limits.ts +176 -0
- package/src/dinov2/service.ts +88 -10
- package/src/dinov2/worker-thread.ts +85 -10
- package/src/embeddings/service.ts +13 -1
- package/src/embeddings/worker-thread.ts +13 -102
- package/src/index.ts +15 -0
- package/src/onnx-availability.ts +78 -0
- package/src/onnx-provider-detect.ts +134 -0
package/src/index.ts
CHANGED
|
@@ -49,6 +49,21 @@ export { DINOv2Service, DINOV2_EMBEDDING_DIMENSION, DINOV2_INPUT_SIZE } from "./
|
|
|
49
49
|
export type { DINOv2ServiceConfig } from "./dinov2/index.js";
|
|
50
50
|
export type { DINOv2WorkerMessage, DINOv2WorkerResponse } from "./dinov2/index.js";
|
|
51
51
|
|
|
52
|
+
// ONNX Runtime availability checker
|
|
53
|
+
export {
|
|
54
|
+
isOnnxRuntimeAvailable,
|
|
55
|
+
OnnxRuntimeUnavailableError,
|
|
56
|
+
safeImportOnnx,
|
|
57
|
+
} from "./onnx-availability.js";
|
|
58
|
+
|
|
59
|
+
// ML Worker Thread resource limits (PR7e-β1)
|
|
60
|
+
export {
|
|
61
|
+
loadMLWorkerResourceLimits,
|
|
62
|
+
getMLWorkerThreadOptions,
|
|
63
|
+
MLWorkerResourceLimitsSchema,
|
|
64
|
+
} from "./config/worker-resource-limits.js";
|
|
65
|
+
export type { MLWorkerResourceLimits } from "./config/worker-resource-limits.js";
|
|
66
|
+
|
|
52
67
|
// Search utilities exports (SearchService removed in v0.1.0)
|
|
53
68
|
export { calculateRRF, mergeWithRRF, normalizeRRFScore, toRankedItems } from "./search/index.js";
|
|
54
69
|
export { executeHybridSearch } from "./search/index.js";
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 TKMD and Reftrix Contributors
|
|
2
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Cached availability checker for onnxruntime-node (optionalDependency).
|
|
6
|
+
* When unavailable, ML features degrade gracefully.
|
|
7
|
+
*
|
|
8
|
+
* @module onnx-availability
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
let _available: boolean | null = null;
|
|
12
|
+
let _unavailableReason: string | null = null;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Check if onnxruntime-node is available (async, caches result).
|
|
16
|
+
*/
|
|
17
|
+
export async function isOnnxRuntimeAvailable(): Promise<boolean> {
|
|
18
|
+
if (_available !== null) return _available;
|
|
19
|
+
try {
|
|
20
|
+
await import("onnxruntime-node");
|
|
21
|
+
_available = true;
|
|
22
|
+
_unavailableReason = null;
|
|
23
|
+
} catch {
|
|
24
|
+
_available = false;
|
|
25
|
+
_unavailableReason = "onnxruntime-node is not installed";
|
|
26
|
+
}
|
|
27
|
+
return _available;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Synchronous check — returns null if not yet probed.
|
|
32
|
+
*/
|
|
33
|
+
export function isOnnxRuntimeAvailableSync(): boolean | null {
|
|
34
|
+
return _available;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Returns the reason onnxruntime-node is unavailable, or null if available.
|
|
39
|
+
*/
|
|
40
|
+
export function getOnnxUnavailableReason(): string | null {
|
|
41
|
+
return _unavailableReason;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Error thrown when ML features require onnxruntime-node but it is not installed.
|
|
46
|
+
*/
|
|
47
|
+
export class OnnxRuntimeUnavailableError extends Error {
|
|
48
|
+
constructor(context?: string) {
|
|
49
|
+
super(
|
|
50
|
+
`ML features require onnxruntime-node which is not available. ` +
|
|
51
|
+
`Install with: pnpm add onnxruntime-node` +
|
|
52
|
+
(context ? ` (${context})` : "")
|
|
53
|
+
);
|
|
54
|
+
this.name = "OnnxRuntimeUnavailableError";
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
|
59
|
+
type OnnxRuntimeModule = typeof import("onnxruntime-node");
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Safely import onnxruntime-node with a sanitized error on failure.
|
|
63
|
+
*/
|
|
64
|
+
export async function safeImportOnnx(): Promise<OnnxRuntimeModule> {
|
|
65
|
+
try {
|
|
66
|
+
return await import("onnxruntime-node");
|
|
67
|
+
} catch {
|
|
68
|
+
throw new OnnxRuntimeUnavailableError();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* For testing: reset cached state.
|
|
74
|
+
*/
|
|
75
|
+
export function _resetForTesting(): void {
|
|
76
|
+
_available = null;
|
|
77
|
+
_unavailableReason = null;
|
|
78
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
2
|
+
/**
|
|
3
|
+
* ONNX Execution Provider Detection Utilities
|
|
4
|
+
*
|
|
5
|
+
* Shared logic for detecting the ONNX execution provider (CPU vs CUDA)
|
|
6
|
+
* based on environment configuration and CUDA shared library availability.
|
|
7
|
+
*
|
|
8
|
+
* Used by both the e5-base embedding worker thread and the DINOv2 worker thread
|
|
9
|
+
* to avoid code duplication. Extracted from embeddings/worker-thread.ts in v0.4.0.
|
|
10
|
+
*
|
|
11
|
+
* @module onnx-provider-detect
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { createRequire } from "node:module";
|
|
15
|
+
import fs from "node:fs";
|
|
16
|
+
import nodePath from "node:path";
|
|
17
|
+
|
|
18
|
+
// =====================================================
|
|
19
|
+
// Types
|
|
20
|
+
// =====================================================
|
|
21
|
+
|
|
22
|
+
export type ExecutionProvider = "cpu" | "cuda";
|
|
23
|
+
|
|
24
|
+
// =====================================================
|
|
25
|
+
// Provider Detection
|
|
26
|
+
// =====================================================
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Detect the ONNX execution provider based on environment configuration.
|
|
30
|
+
*
|
|
31
|
+
* Checks ONNX_EXECUTION_PROVIDER env var and verifies that the CUDA
|
|
32
|
+
* provider shared library is available on disk. Falls back to CPU
|
|
33
|
+
* gracefully if the provider is not installed.
|
|
34
|
+
*
|
|
35
|
+
* @param logPrefix - Log prefix for warning messages (e.g. "EmbeddingWorker", "DINOv2Worker")
|
|
36
|
+
*/
|
|
37
|
+
export function detectExecutionProvider(logPrefix?: string): ExecutionProvider {
|
|
38
|
+
const prefix = logPrefix ?? "OnnxProvider";
|
|
39
|
+
const envProvider = process.env.ONNX_EXECUTION_PROVIDER;
|
|
40
|
+
|
|
41
|
+
if (envProvider === "cuda" || envProvider === "rocm") {
|
|
42
|
+
const cudaAvailable = verifyCudaAvailability(logPrefix);
|
|
43
|
+
if (cudaAvailable) {
|
|
44
|
+
return "cuda";
|
|
45
|
+
}
|
|
46
|
+
console.warn(
|
|
47
|
+
"[%s] ONNX_EXECUTION_PROVIDER=%s but CUDA provider not available, falling back to CPU",
|
|
48
|
+
prefix,
|
|
49
|
+
envProvider
|
|
50
|
+
);
|
|
51
|
+
return "cpu";
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return "cpu";
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// =====================================================
|
|
58
|
+
// CUDA Availability Verification
|
|
59
|
+
// =====================================================
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Verify that CUDA provider (libonnxruntime_providers_cuda.so) is available.
|
|
63
|
+
*
|
|
64
|
+
* onnxruntime-node can download the CUDA provider shared library via
|
|
65
|
+
* `ONNXRUNTIME_NODE_INSTALL_CUDA=v12 node .../install.js`. This function
|
|
66
|
+
* checks for its presence on disk rather than trying to resolve a
|
|
67
|
+
* non-existent npm package (onnxruntime-gpu is Python-only).
|
|
68
|
+
*
|
|
69
|
+
* @param logPrefix - Log prefix for warning messages
|
|
70
|
+
*/
|
|
71
|
+
export function verifyCudaAvailability(logPrefix?: string): boolean {
|
|
72
|
+
const prefix = logPrefix ?? "OnnxProvider";
|
|
73
|
+
try {
|
|
74
|
+
const esmRequire = createRequire(import.meta.url);
|
|
75
|
+
const ortNodePath = esmRequire.resolve("onnxruntime-node");
|
|
76
|
+
// require.resolve returns e.g. .../onnxruntime-node/dist/index.js
|
|
77
|
+
// Walk up to package root by finding the directory containing package.json
|
|
78
|
+
let packageDir = nodePath.dirname(ortNodePath);
|
|
79
|
+
for (let i = 0; i < 5; i++) {
|
|
80
|
+
if (fs.existsSync(nodePath.join(packageDir, "package.json"))) break;
|
|
81
|
+
packageDir = nodePath.dirname(packageDir);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Search across napi versions (v3, v6, etc.) for CUDA provider
|
|
85
|
+
const binDir = nodePath.join(packageDir, "bin");
|
|
86
|
+
if (fs.existsSync(binDir)) {
|
|
87
|
+
const napiDirs = fs.readdirSync(binDir).filter((d) => d.startsWith("napi-v"));
|
|
88
|
+
for (const napiDir of napiDirs) {
|
|
89
|
+
const cudaProviderPath = nodePath.join(
|
|
90
|
+
binDir,
|
|
91
|
+
napiDir,
|
|
92
|
+
"linux",
|
|
93
|
+
"x64",
|
|
94
|
+
"libonnxruntime_providers_cuda.so"
|
|
95
|
+
);
|
|
96
|
+
if (fs.existsSync(cudaProviderPath)) {
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
console.warn("[%s] CUDA provider not found in: %s", prefix, binDir);
|
|
103
|
+
return false;
|
|
104
|
+
} catch {
|
|
105
|
+
console.warn("[%s] Cannot verify CUDA provider: onnxruntime-node not found", prefix);
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// =====================================================
|
|
111
|
+
// LD_LIBRARY_PATH Check
|
|
112
|
+
// =====================================================
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Verify that LD_LIBRARY_PATH is set at the OS level (not just process.env).
|
|
116
|
+
*
|
|
117
|
+
* dlopen() reads LD_LIBRARY_PATH from the kernel environment (/proc/self/environ),
|
|
118
|
+
* NOT from process.env modifications made at runtime. If LD_LIBRARY_PATH was set
|
|
119
|
+
* after process startup (e.g. by loadEnvLocal()), dlopen() cannot find CUDA
|
|
120
|
+
* libraries and ONNX Runtime CUDA provider initialization will segfault or throw.
|
|
121
|
+
*
|
|
122
|
+
* Returns true only if LD_LIBRARY_PATH was present in the original process environment.
|
|
123
|
+
*
|
|
124
|
+
* @returns true if LD_LIBRARY_PATH is set at OS level, or if /proc/self/environ is unavailable
|
|
125
|
+
*/
|
|
126
|
+
export function isLdLibraryPathSetAtOsLevel(): boolean {
|
|
127
|
+
try {
|
|
128
|
+
const procEnv = fs.readFileSync("/proc/self/environ", "utf-8");
|
|
129
|
+
return procEnv.includes("LD_LIBRARY_PATH");
|
|
130
|
+
} catch {
|
|
131
|
+
// /proc/self/environ not available (non-Linux) — assume set
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
}
|