gitnexus 1.6.8-rc.7 → 1.6.8-rc.8
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.
|
@@ -21,6 +21,7 @@ import { isHttpMode, getHttpDimensions, httpEmbed } from './http-client.js';
|
|
|
21
21
|
import { resolveEmbeddingConfig } from './config.js';
|
|
22
22
|
import { applyHfEnvOverrides, isHfDownloadFailure, withHfDownloadRetry } from './hf-env.js';
|
|
23
23
|
import { getLocalEmbeddingRuntimeBlocker } from './runtime-support.js';
|
|
24
|
+
import { ensureOnnxRuntimeCommonResolvable } from './onnxruntime-common-resolver.js';
|
|
24
25
|
import { logger } from '../logger.js';
|
|
25
26
|
/**
|
|
26
27
|
* Check whether the onnxruntime-node package that @huggingface/transformers
|
|
@@ -147,6 +148,9 @@ export const initEmbedder = async (onProgress, config = {}, forceDevice) => {
|
|
|
147
148
|
try {
|
|
148
149
|
// Lazy-load transformers.js only after the runtime guard has passed, so
|
|
149
150
|
// unsupported platforms never reach the native ONNX import (#1515).
|
|
151
|
+
// Under pnpm-strict / `pnpm dlx`, transformers' phantom `onnxruntime-common`
|
|
152
|
+
// import is unresolvable; register the fallback resolver first (#307).
|
|
153
|
+
ensureOnnxRuntimeCommonResolvable();
|
|
150
154
|
const { pipeline, env } = await import('@huggingface/transformers');
|
|
151
155
|
// Configure transformers.js environment
|
|
152
156
|
env.allowLocalModels = false;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Make `@huggingface/transformers`' phantom `onnxruntime-common` import
|
|
3
|
+
* resolvable under strict package-manager layouts (#307, #2069).
|
|
4
|
+
*
|
|
5
|
+
* ## Why
|
|
6
|
+
* transformers' shipped `dist/transformers.node.mjs` does a bare
|
|
7
|
+
* `import 'onnxruntime-common'`, but transformers' `package.json` never declares
|
|
8
|
+
* onnxruntime-common (it lists onnxruntime-node / onnxruntime-web / sharp). With
|
|
9
|
+
* npm's flat `node_modules` — or pnpm with hoisting — the package is hoisted to
|
|
10
|
+
* a directory on transformers' resolution path and the import resolves by
|
|
11
|
+
* accident. Under pnpm's isolated store (and therefore `pnpm dlx` / `pnpx`), a
|
|
12
|
+
* package only sees its *declared* deps, so the import dies with
|
|
13
|
+
* `ERR_MODULE_NOT_FOUND` before `analyze --embeddings` can run.
|
|
14
|
+
*
|
|
15
|
+
* Declaring onnxruntime-common in gitnexus' own dependencies (#2074) does NOT
|
|
16
|
+
* fix this under pnpm: Node resolves the bare specifier from *transformers'*
|
|
17
|
+
* module scope, not ours, and overrides/resolutions can only re-version an
|
|
18
|
+
* existing edge, never add the missing one.
|
|
19
|
+
*
|
|
20
|
+
* ## What this does
|
|
21
|
+
* Install a synchronous, in-thread ESM resolution hook (`module.registerHooks`,
|
|
22
|
+
* Node >= 22.15) that redirects `onnxruntime-common` to a copy gitnexus can
|
|
23
|
+
* resolve — but only when the default resolver fails. The redirect target is
|
|
24
|
+
* preferentially the `onnxruntime-common` that `onnxruntime-node` (the native
|
|
25
|
+
* binding transformers actually loads) itself depends on, so the redirected copy
|
|
26
|
+
* is version-matched to that binding even under `pnpm dlx` — where gitnexus'
|
|
27
|
+
* npm-style `overrides` block does NOT apply, because it is honoured only from a
|
|
28
|
+
* root manifest and gitnexus is a transitive dependency there. It falls back to
|
|
29
|
+
* gitnexus' own direct `onnxruntime-common` dependency when that chain can't be
|
|
30
|
+
* walked. onnxruntime-common is a stable, pure-JS package whose `Tensor` surface
|
|
31
|
+
* is unchanged across 1.24–1.26, so either target is API-compatible. On working
|
|
32
|
+
* layouts the default resolver succeeds first and the hook never fires, so
|
|
33
|
+
* behaviour is unchanged.
|
|
34
|
+
*
|
|
35
|
+
* `registerHooks` (synchronous, in-thread) is preferred over the older
|
|
36
|
+
* `module.register` (async, off-thread, now deprecated — DEP0205, removed in
|
|
37
|
+
* Node 26): the redirect is a one-line conditional that needs no worker thread,
|
|
38
|
+
* no separate hook module, and no `data` marshalling.
|
|
39
|
+
*
|
|
40
|
+
* ## Safety
|
|
41
|
+
* Best-effort and idempotent. The hook is installed lazily, only on the
|
|
42
|
+
* local-embedding code path (after parsing), so it is never registered during
|
|
43
|
+
* analysis, in the parse workers, or in HTTP embedding mode. Once installed it
|
|
44
|
+
* is process-global: its resolve closure runs for every subsequent module
|
|
45
|
+
* resolution, but it passes all of them through untouched and only substitutes a
|
|
46
|
+
* result for the exact `onnxruntime-common` specifier when that specifier is
|
|
47
|
+
* genuinely absent — so it cannot mask an unrelated resolution error, and the
|
|
48
|
+
* per-resolution cost is a single string comparison.
|
|
49
|
+
*
|
|
50
|
+
* `module.registerHooks` is marked `@experimental` and requires Node >= 22.15
|
|
51
|
+
* (the gitnexus engines floor is >= 22.0.0). On older runtimes it is absent and
|
|
52
|
+
* this is a graceful no-op: embeddings then resolve onnxruntime-common exactly
|
|
53
|
+
* as before — fine on hoisted layouts. Any failure during installation is
|
|
54
|
+
* swallowed.
|
|
55
|
+
*/
|
|
56
|
+
import { registerHooks, createRequire } from 'node:module';
|
|
57
|
+
import { pathToFileURL } from 'node:url';
|
|
58
|
+
import { logger } from '../logger.js';
|
|
59
|
+
let attempted = false;
|
|
60
|
+
/**
|
|
61
|
+
* Compute the file: URL the hook redirects `onnxruntime-common` to.
|
|
62
|
+
*
|
|
63
|
+
* Prefer the copy `onnxruntime-node` (the native binding transformers loads)
|
|
64
|
+
* depends on, so the redirected module is version-matched to the binding even
|
|
65
|
+
* under `pnpm dlx`, where transformers keeps its own pinned onnxruntime-node.
|
|
66
|
+
* The walk resolves transformers' MAIN entry — NOT `@huggingface/transformers/
|
|
67
|
+
* package.json`, which transformers' `exports` map blocks
|
|
68
|
+
* (`ERR_PACKAGE_PATH_NOT_EXPORTED`) — then onnxruntime-node, then its
|
|
69
|
+
* onnxruntime-common. Falls back to gitnexus' own direct dependency (always
|
|
70
|
+
* resolvable from our scope) when any step fails.
|
|
71
|
+
*/
|
|
72
|
+
const resolveOnnxRuntimeCommonUrl = () => {
|
|
73
|
+
const require = createRequire(import.meta.url);
|
|
74
|
+
try {
|
|
75
|
+
const transformersMain = require.resolve('@huggingface/transformers');
|
|
76
|
+
const ortNodePkg = createRequire(transformersMain).resolve('onnxruntime-node/package.json');
|
|
77
|
+
const common = createRequire(ortNodePkg).resolve('onnxruntime-common');
|
|
78
|
+
return pathToFileURL(common).href;
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return pathToFileURL(require.resolve('onnxruntime-common')).href;
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Idempotently install the onnxruntime-common resolution fallback. Call once
|
|
86
|
+
* immediately before the dynamic `import('@huggingface/transformers')` on the
|
|
87
|
+
* local-embedding path.
|
|
88
|
+
*/
|
|
89
|
+
export const ensureOnnxRuntimeCommonResolvable = () => {
|
|
90
|
+
if (attempted)
|
|
91
|
+
return;
|
|
92
|
+
// Mark attempted up-front: a failed attempt must not retry on every
|
|
93
|
+
// initEmbedder() call, and the hook is process-global — once is enough.
|
|
94
|
+
attempted = true;
|
|
95
|
+
try {
|
|
96
|
+
// Node < 22.15 (the gitnexus engines floor is >= 22.0.0): no synchronous
|
|
97
|
+
// hooks API. Degrade gracefully — the import still works on hoisted layouts.
|
|
98
|
+
if (typeof registerHooks !== 'function')
|
|
99
|
+
return;
|
|
100
|
+
const redirectUrl = resolveOnnxRuntimeCommonUrl();
|
|
101
|
+
registerHooks({
|
|
102
|
+
resolve(specifier, context, nextResolve) {
|
|
103
|
+
if (specifier !== 'onnxruntime-common')
|
|
104
|
+
return nextResolve(specifier, context);
|
|
105
|
+
// Honour a real, package-manager-provided copy when one is on the path
|
|
106
|
+
// (npm / hoisted pnpm); only substitute ours when the specifier is
|
|
107
|
+
// genuinely absent.
|
|
108
|
+
try {
|
|
109
|
+
return nextResolve(specifier, context);
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
// The phantom import surfaces as ERR_MODULE_NOT_FOUND (or, for a
|
|
113
|
+
// present-but-exports-broken copy, ERR_PACKAGE_PATH_NOT_EXPORTED).
|
|
114
|
+
// Rethrow anything else so a genuinely broken install is not masked.
|
|
115
|
+
const code = err?.code;
|
|
116
|
+
if (code === 'ERR_MODULE_NOT_FOUND' || code === 'ERR_PACKAGE_PATH_NOT_EXPORTED') {
|
|
117
|
+
return { url: redirectUrl, shortCircuit: true };
|
|
118
|
+
}
|
|
119
|
+
throw err;
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
logger.debug({ redirectUrl }, 'Installed onnxruntime-common resolution fallback (#307)');
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
// Never block embeddings on the fallback. On layouts where the package
|
|
127
|
+
// manager already resolves onnxruntime-common this is unnecessary anyway.
|
|
128
|
+
logger.debug({ err: err instanceof Error ? err.message : String(err) }, 'onnxruntime-common resolution fallback not installed');
|
|
129
|
+
}
|
|
130
|
+
};
|
|
@@ -8,6 +8,7 @@ import { isHttpMode, getHttpDimensions, httpEmbedQuery, } from '../../core/embed
|
|
|
8
8
|
import { resolveEmbeddingConfig } from '../../core/embeddings/config.js';
|
|
9
9
|
import { applyHfEnvOverrides, isHfDownloadFailure, withHfDownloadRetry, } from '../../core/embeddings/hf-env.js';
|
|
10
10
|
import { getLocalEmbeddingRuntimeBlocker } from '../../core/embeddings/runtime-support.js';
|
|
11
|
+
import { ensureOnnxRuntimeCommonResolvable } from '../../core/embeddings/onnxruntime-common-resolver.js';
|
|
11
12
|
import { silenceStdout, restoreStdout, realStderrWrite } from '../../core/lbug/pool-adapter.js';
|
|
12
13
|
import { logger } from '../../core/logger.js';
|
|
13
14
|
// Model config
|
|
@@ -43,6 +44,9 @@ export const initEmbedder = async () => {
|
|
|
43
44
|
try {
|
|
44
45
|
// Lazy-load transformers.js only after the runtime guard has passed, so
|
|
45
46
|
// unsupported platforms never reach the native ONNX import (#1515).
|
|
47
|
+
// Under pnpm-strict / `pnpm dlx`, transformers' phantom `onnxruntime-common`
|
|
48
|
+
// import is unresolvable; register the fallback resolver first (#307).
|
|
49
|
+
ensureOnnxRuntimeCommonResolvable();
|
|
46
50
|
const { pipeline, env } = await import('@huggingface/transformers');
|
|
47
51
|
env.allowLocalModels = false;
|
|
48
52
|
// Bridge user-controlled env vars to transformers.js: HF_HOME →
|
package/package.json
CHANGED