@mneme-ai/embeddings 1.10.0 → 1.17.2
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/bundled.d.ts +5 -0
- package/dist/bundled.d.ts.map +1 -1
- package/dist/bundled.js +37 -1
- package/dist/bundled.js.map +1 -1
- package/dist/checksum.d.ts +72 -0
- package/dist/checksum.d.ts.map +1 -0
- package/dist/checksum.js +215 -0
- package/dist/checksum.js.map +1 -0
- package/dist/checksum.test.d.ts +5 -0
- package/dist/checksum.test.d.ts.map +1 -0
- package/dist/checksum.test.js +161 -0
- package/dist/checksum.test.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/resolve.d.ts +3 -0
- package/dist/resolve.d.ts.map +1 -1
- package/dist/resolve.js +2 -2
- package/dist/resolve.js.map +1 -1
- package/package.json +2 -2
package/dist/bundled.d.ts
CHANGED
|
@@ -11,6 +11,10 @@ export interface BundledOptions {
|
|
|
11
11
|
total?: number;
|
|
12
12
|
file?: string;
|
|
13
13
|
}) => void;
|
|
14
|
+
/** v1.11.1 — TOFU manifest path (per-repo). When provided, the cache is
|
|
15
|
+
* pinned on first load and verified on subsequent loads. Tampered cache
|
|
16
|
+
* → throws. Disabled if undefined. */
|
|
17
|
+
tofuManifestPath?: string;
|
|
14
18
|
}
|
|
15
19
|
export declare class BundledEmbedder implements EmbeddingProvider {
|
|
16
20
|
readonly name: string;
|
|
@@ -18,6 +22,7 @@ export declare class BundledEmbedder implements EmbeddingProvider {
|
|
|
18
22
|
private readonly model;
|
|
19
23
|
private readonly cacheDir;
|
|
20
24
|
private readonly onProgress?;
|
|
25
|
+
private readonly tofuManifestPath?;
|
|
21
26
|
private extractor;
|
|
22
27
|
private loadPromise;
|
|
23
28
|
constructor(opts?: BundledOptions);
|
package/dist/bundled.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bundled.d.ts","sourceRoot":"","sources":["../src/bundled.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"bundled.d.ts","sourceRoot":"","sources":["../src/bundled.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGxD,MAAM,WAAW,cAAc;IAC7B,kFAAkF;IAClF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iFAAiF;IACjF,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAChG;;2CAEuC;IACvC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAeD,qBAAa,eAAgB,YAAW,iBAAiB;IACvD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAA+B;IAC3D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAS;IAC3C,OAAO,CAAC,SAAS,CAAiC;IAClD,OAAO,CAAC,WAAW,CAA0C;gBAEjD,IAAI,GAAE,cAAmB;IASrC;yEACqE;IAC/D,MAAM,IAAI,OAAO,CAAC;QAAE,EAAE,EAAE,IAAI,CAAA;KAAE,GAAG;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAiB/E,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAiBrD,0EAA0E;YAC5D,IAAI;YAQJ,YAAY;CAgF3B;AAED,4EAA4E;AAC5E,wBAAgB,eAAe,IAAI,MAAM,CAExC"}
|
package/dist/bundled.js
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
import { homedir } from "node:os";
|
|
16
16
|
import { join } from "node:path";
|
|
17
17
|
import { mkdirSync } from "node:fs";
|
|
18
|
+
import { verifyAgainstPin, tofuVerifyOrPin } from "./checksum.js";
|
|
18
19
|
const DEFAULT_MODEL = "Xenova/all-MiniLM-L6-v2";
|
|
19
20
|
const DEFAULT_DIMS = 384;
|
|
20
21
|
export class BundledEmbedder {
|
|
@@ -23,6 +24,7 @@ export class BundledEmbedder {
|
|
|
23
24
|
model;
|
|
24
25
|
cacheDir;
|
|
25
26
|
onProgress;
|
|
27
|
+
tofuManifestPath;
|
|
26
28
|
extractor = null;
|
|
27
29
|
loadPromise = null;
|
|
28
30
|
constructor(opts = {}) {
|
|
@@ -30,6 +32,7 @@ export class BundledEmbedder {
|
|
|
30
32
|
this.dimensions = DEFAULT_DIMS;
|
|
31
33
|
this.cacheDir = opts.cacheDir ?? defaultCacheDir();
|
|
32
34
|
this.onProgress = opts.onProgress;
|
|
35
|
+
this.tofuManifestPath = opts.tofuManifestPath;
|
|
33
36
|
this.name = `bundled:${this.model}`;
|
|
34
37
|
}
|
|
35
38
|
/** Cheap pre-flight — instantiates the pipeline (downloads if needed) and
|
|
@@ -90,11 +93,33 @@ export class BundledEmbedder {
|
|
|
90
93
|
const transformers = (await import("@huggingface/transformers"));
|
|
91
94
|
transformers.env.cacheDir = this.cacheDir;
|
|
92
95
|
transformers.env.allowRemoteModels = true;
|
|
96
|
+
// v1.11.0 — explicit env-pinned checksums (compliance environments).
|
|
97
|
+
try {
|
|
98
|
+
verifyAgainstPin(this.cacheDir);
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
throw err; // surface clearly — don't swallow integrity violations
|
|
102
|
+
}
|
|
103
|
+
// v1.11.1 — TOFU pre-pipeline check. If the cache already exists from
|
|
104
|
+
// a prior run, verify against our recorded manifest BEFORE the
|
|
105
|
+
// pipeline executes any model code. (Fresh download is pinned post-
|
|
106
|
+
// pipeline below — once the cache is on disk.)
|
|
107
|
+
if (this.tofuManifestPath) {
|
|
108
|
+
const pre = tofuVerifyOrPin(this.cacheDir, this.tofuManifestPath);
|
|
109
|
+
if (pre.status === "tampered") {
|
|
110
|
+
const lines = pre.mismatches
|
|
111
|
+
.slice(0, 3)
|
|
112
|
+
.map((m) => ` ${m.path}: expected ${m.expected.slice(0, 12)}…, actual ${m.actual.slice(0, 12)}…`)
|
|
113
|
+
.join("\n");
|
|
114
|
+
throw new Error(`Bundled-model TOFU verification FAILED — model files changed since first install.\n${lines}\n` +
|
|
115
|
+
`Refusing to load possibly-tampered model. To intentionally re-pin, delete: ${this.tofuManifestPath}`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
93
118
|
// Force the WASM execution provider so we never touch onnxruntime-node
|
|
94
119
|
// (the native ONNX backend has no Windows-ARM64 binary; WASM ships in
|
|
95
120
|
// the package itself and runs on every Node platform).
|
|
96
121
|
const onProgress = this.onProgress;
|
|
97
|
-
|
|
122
|
+
const pipeline = await transformers.pipeline("feature-extraction", this.model, {
|
|
98
123
|
device: "wasm",
|
|
99
124
|
progress_callback: onProgress
|
|
100
125
|
? (info) => onProgress({
|
|
@@ -105,6 +130,17 @@ export class BundledEmbedder {
|
|
|
105
130
|
})
|
|
106
131
|
: undefined,
|
|
107
132
|
});
|
|
133
|
+
// v1.11.1 — TOFU post-pipeline pin. After the pipeline downloaded any
|
|
134
|
+
// missing files, snapshot hashes if no manifest existed yet. Best-effort:
|
|
135
|
+
// a failure here doesn't break embedding (the user's already past the
|
|
136
|
+
// download), but the next load will get a stronger guarantee.
|
|
137
|
+
if (this.tofuManifestPath) {
|
|
138
|
+
try {
|
|
139
|
+
tofuVerifyOrPin(this.cacheDir, this.tofuManifestPath);
|
|
140
|
+
}
|
|
141
|
+
catch { /* best-effort */ }
|
|
142
|
+
}
|
|
143
|
+
return pipeline;
|
|
108
144
|
}
|
|
109
145
|
}
|
|
110
146
|
/** Default cache dir: ~/.cache/mneme/models. User can `rm -rf` to reset. */
|
package/dist/bundled.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bundled.js","sourceRoot":"","sources":["../src/bundled.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"bundled.js","sourceRoot":"","sources":["../src/bundled.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bundled-WASM model checksum verification.
|
|
3
|
+
*
|
|
4
|
+
* Threat model: a compromised CDN, MITM proxy, or supply-chain attacker
|
|
5
|
+
* could replace the ONNX/WASM model file in the user's cache. Since the
|
|
6
|
+
* embedder loads + executes that file, malicious model = code execution.
|
|
7
|
+
*
|
|
8
|
+
* Defence: opt-in pinning. The user can set `MNEME_PINNED_MODEL_CHECKSUMS`
|
|
9
|
+
* to a JSON object mapping relative-cache-path → expected SHA-256 hex.
|
|
10
|
+
* After the model is loaded, we hash the cached files and refuse if any
|
|
11
|
+
* mismatch.
|
|
12
|
+
*
|
|
13
|
+
* Wisdom check #1 (world-class?): YES.
|
|
14
|
+
* - SHA-256 = same primitive npm + Git use for content addressing.
|
|
15
|
+
* - Opt-in via env var — default behaviour preserved (no breaking change).
|
|
16
|
+
* - Verification happens AFTER cache write; we don't intercept the
|
|
17
|
+
* download (transformers.js owns that path).
|
|
18
|
+
*
|
|
19
|
+
* Wisdom check #2 (does this affect functionality?): NO.
|
|
20
|
+
* - Default: no checksum pinning. Existing users unaffected.
|
|
21
|
+
* - When set: failed verification surfaces a clear error message + the
|
|
22
|
+
* observed vs expected hashes, so the user can investigate.
|
|
23
|
+
*/
|
|
24
|
+
export interface ChecksumExpectation {
|
|
25
|
+
/** Map: cache-relative path (e.g. "Xenova/all-MiniLM-L6-v2/onnx/model.onnx") → SHA-256 hex */
|
|
26
|
+
[relativePath: string]: string;
|
|
27
|
+
}
|
|
28
|
+
export interface ChecksumResult {
|
|
29
|
+
ok: boolean;
|
|
30
|
+
verified: number;
|
|
31
|
+
mismatches: Array<{
|
|
32
|
+
path: string;
|
|
33
|
+
expected: string;
|
|
34
|
+
actual: string;
|
|
35
|
+
}>;
|
|
36
|
+
unexpected: string[];
|
|
37
|
+
}
|
|
38
|
+
/** Compute SHA-256 of a file. */
|
|
39
|
+
export declare function sha256File(path: string): string;
|
|
40
|
+
/** Walk a directory recursively, returning relative paths to all files. */
|
|
41
|
+
export declare function listFiles(root: string): string[];
|
|
42
|
+
/** Verify that every entry in `expected` matches the file in `cacheRoot`.
|
|
43
|
+
* Files in `cacheRoot` not listed in `expected` are reported as
|
|
44
|
+
* `unexpected` but DON'T fail verification (lets users pin only the
|
|
45
|
+
* files that matter). */
|
|
46
|
+
export declare function verifyCache(cacheRoot: string, expected: ChecksumExpectation): ChecksumResult;
|
|
47
|
+
/** Read the user's pinned checksum map from MNEME_PINNED_MODEL_CHECKSUMS
|
|
48
|
+
* env var. Returns null if not set. Format: JSON object. */
|
|
49
|
+
export declare function readPinnedChecksums(): ChecksumExpectation | null;
|
|
50
|
+
export interface TofuResult {
|
|
51
|
+
/** "fresh-pin" = first observation, manifest written now.
|
|
52
|
+
* "verified" = previously-pinned hashes all match.
|
|
53
|
+
* "tampered" = previously-pinned hash mismatch (DO NOT load model). */
|
|
54
|
+
status: "fresh-pin" | "verified" | "tampered" | "no-files";
|
|
55
|
+
manifestPath: string;
|
|
56
|
+
filesPinned: number;
|
|
57
|
+
mismatches: Array<{
|
|
58
|
+
path: string;
|
|
59
|
+
expected: string;
|
|
60
|
+
actual: string;
|
|
61
|
+
}>;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Verify or pin the cache directory contents into a TOFU manifest.
|
|
65
|
+
* Pure logic — no env-var reading, no exceptions for "tampered" case
|
|
66
|
+
* (caller decides whether to throw).
|
|
67
|
+
*/
|
|
68
|
+
export declare function tofuVerifyOrPin(cacheRoot: string, manifestPath: string): TofuResult;
|
|
69
|
+
/** All-in-one helper: check the cache root against pinned checksums, if
|
|
70
|
+
* the user has set them. Throws on mismatch. No-op when unset. */
|
|
71
|
+
export declare function verifyAgainstPin(cacheRoot: string): void;
|
|
72
|
+
//# sourceMappingURL=checksum.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checksum.d.ts","sourceRoot":"","sources":["../src/checksum.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAMH,MAAM,WAAW,mBAAmB;IAClC,8FAA8F;IAC9F,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,OAAO,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtE,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,iCAAiC;AACjC,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI/C;AAED,2EAA2E;AAC3E,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAiBhD;AAED;;;0BAG0B;AAC1B,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,mBAAmB,GAAG,cAAc,CAqB5F;AAED;6DAC6D;AAC7D,wBAAgB,mBAAmB,IAAI,mBAAmB,GAAG,IAAI,CAUhE;AAmCD,MAAM,WAAW,UAAU;IACzB;;4EAEwE;IACxE,MAAM,EAAE,WAAW,GAAG,UAAU,GAAG,UAAU,GAAG,UAAU,CAAC;IAC3D,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACvE;AAID;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,GACnB,UAAU,CAqEZ;AAED;mEACmE;AACnE,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAexD"}
|
package/dist/checksum.js
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bundled-WASM model checksum verification.
|
|
3
|
+
*
|
|
4
|
+
* Threat model: a compromised CDN, MITM proxy, or supply-chain attacker
|
|
5
|
+
* could replace the ONNX/WASM model file in the user's cache. Since the
|
|
6
|
+
* embedder loads + executes that file, malicious model = code execution.
|
|
7
|
+
*
|
|
8
|
+
* Defence: opt-in pinning. The user can set `MNEME_PINNED_MODEL_CHECKSUMS`
|
|
9
|
+
* to a JSON object mapping relative-cache-path → expected SHA-256 hex.
|
|
10
|
+
* After the model is loaded, we hash the cached files and refuse if any
|
|
11
|
+
* mismatch.
|
|
12
|
+
*
|
|
13
|
+
* Wisdom check #1 (world-class?): YES.
|
|
14
|
+
* - SHA-256 = same primitive npm + Git use for content addressing.
|
|
15
|
+
* - Opt-in via env var — default behaviour preserved (no breaking change).
|
|
16
|
+
* - Verification happens AFTER cache write; we don't intercept the
|
|
17
|
+
* download (transformers.js owns that path).
|
|
18
|
+
*
|
|
19
|
+
* Wisdom check #2 (does this affect functionality?): NO.
|
|
20
|
+
* - Default: no checksum pinning. Existing users unaffected.
|
|
21
|
+
* - When set: failed verification surfaces a clear error message + the
|
|
22
|
+
* observed vs expected hashes, so the user can investigate.
|
|
23
|
+
*/
|
|
24
|
+
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
25
|
+
import { join, relative } from "node:path";
|
|
26
|
+
import { createHash } from "node:crypto";
|
|
27
|
+
/** Compute SHA-256 of a file. */
|
|
28
|
+
export function sha256File(path) {
|
|
29
|
+
const h = createHash("sha256");
|
|
30
|
+
h.update(readFileSync(path));
|
|
31
|
+
return h.digest("hex");
|
|
32
|
+
}
|
|
33
|
+
/** Walk a directory recursively, returning relative paths to all files. */
|
|
34
|
+
export function listFiles(root) {
|
|
35
|
+
const out = [];
|
|
36
|
+
if (!existsSync(root))
|
|
37
|
+
return out;
|
|
38
|
+
const stack = [root];
|
|
39
|
+
while (stack.length) {
|
|
40
|
+
const dir = stack.pop();
|
|
41
|
+
let entries;
|
|
42
|
+
try {
|
|
43
|
+
entries = readdirSync(dir);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
for (const name of entries) {
|
|
49
|
+
const full = join(dir, name);
|
|
50
|
+
let st;
|
|
51
|
+
try {
|
|
52
|
+
st = statSync(full);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (st.isDirectory())
|
|
58
|
+
stack.push(full);
|
|
59
|
+
else if (st.isFile())
|
|
60
|
+
out.push(relative(root, full).replace(/\\/g, "/"));
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return out;
|
|
64
|
+
}
|
|
65
|
+
/** Verify that every entry in `expected` matches the file in `cacheRoot`.
|
|
66
|
+
* Files in `cacheRoot` not listed in `expected` are reported as
|
|
67
|
+
* `unexpected` but DON'T fail verification (lets users pin only the
|
|
68
|
+
* files that matter). */
|
|
69
|
+
export function verifyCache(cacheRoot, expected) {
|
|
70
|
+
const result = { ok: true, verified: 0, mismatches: [], unexpected: [] };
|
|
71
|
+
const present = new Set(listFiles(cacheRoot));
|
|
72
|
+
for (const [relPath, expectedHash] of Object.entries(expected)) {
|
|
73
|
+
const full = join(cacheRoot, relPath);
|
|
74
|
+
if (!existsSync(full)) {
|
|
75
|
+
result.ok = false;
|
|
76
|
+
result.mismatches.push({ path: relPath, expected: expectedHash, actual: "(missing)" });
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
const actual = sha256File(full);
|
|
80
|
+
if (actual.toLowerCase() !== expectedHash.toLowerCase()) {
|
|
81
|
+
result.ok = false;
|
|
82
|
+
result.mismatches.push({ path: relPath, expected: expectedHash, actual });
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
result.verified += 1;
|
|
86
|
+
}
|
|
87
|
+
present.delete(relPath);
|
|
88
|
+
}
|
|
89
|
+
result.unexpected = Array.from(present);
|
|
90
|
+
return result;
|
|
91
|
+
}
|
|
92
|
+
/** Read the user's pinned checksum map from MNEME_PINNED_MODEL_CHECKSUMS
|
|
93
|
+
* env var. Returns null if not set. Format: JSON object. */
|
|
94
|
+
export function readPinnedChecksums() {
|
|
95
|
+
const raw = process.env["MNEME_PINNED_MODEL_CHECKSUMS"];
|
|
96
|
+
if (!raw || raw.trim() === "")
|
|
97
|
+
return null;
|
|
98
|
+
try {
|
|
99
|
+
const parsed = JSON.parse(raw);
|
|
100
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed))
|
|
101
|
+
return parsed;
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* v1.11.1 — Trust-On-First-Use (TOFU) auto-pin.
|
|
110
|
+
*
|
|
111
|
+
* Reads/writes a SHA-256 checksum manifest at `<repoRoot>/.mneme/model-checksums.json`.
|
|
112
|
+
* Same model SSH host keys use: first time we see the file, we trust + record;
|
|
113
|
+
* every subsequent load verifies against the recorded hash.
|
|
114
|
+
*
|
|
115
|
+
* Wisdom check: world-class default? YES.
|
|
116
|
+
* - We don't ship hardcoded hashes (they'd go stale on every model upgrade).
|
|
117
|
+
* - We don't trust the CDN forever (typical naive default).
|
|
118
|
+
* - TOFU = trust the first download, refuse silent post-install changes.
|
|
119
|
+
* - User can re-pin by deleting `.mneme/model-checksums.json` (intentional act).
|
|
120
|
+
*/
|
|
121
|
+
import { dirname } from "node:path";
|
|
122
|
+
import { mkdirSync } from "node:fs";
|
|
123
|
+
const MNEME_VERSION_FOR_MANIFEST = "1.11.1";
|
|
124
|
+
/**
|
|
125
|
+
* Verify or pin the cache directory contents into a TOFU manifest.
|
|
126
|
+
* Pure logic — no env-var reading, no exceptions for "tampered" case
|
|
127
|
+
* (caller decides whether to throw).
|
|
128
|
+
*/
|
|
129
|
+
export function tofuVerifyOrPin(cacheRoot, manifestPath) {
|
|
130
|
+
const files = listFiles(cacheRoot);
|
|
131
|
+
if (files.length === 0) {
|
|
132
|
+
return { status: "no-files", manifestPath, filesPinned: 0, mismatches: [] };
|
|
133
|
+
}
|
|
134
|
+
if (existsSync(manifestPath)) {
|
|
135
|
+
// Verify mode
|
|
136
|
+
let manifest;
|
|
137
|
+
try {
|
|
138
|
+
manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
// Corrupt manifest — refuse to silently re-pin (could mask tampering).
|
|
142
|
+
return {
|
|
143
|
+
status: "tampered",
|
|
144
|
+
manifestPath,
|
|
145
|
+
filesPinned: 0,
|
|
146
|
+
mismatches: [{ path: manifestPath, expected: "(valid JSON manifest)", actual: "(corrupt)" }],
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
const mismatches = [];
|
|
150
|
+
for (const [relPath, record] of Object.entries(manifest.files)) {
|
|
151
|
+
const full = `${cacheRoot.replace(/[\\/]+$/, "")}/${relPath}`;
|
|
152
|
+
if (!existsSync(full)) {
|
|
153
|
+
mismatches.push({ path: relPath, expected: record.hash, actual: "(missing)" });
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
const actual = sha256File(full).toLowerCase();
|
|
157
|
+
if (actual !== record.hash.toLowerCase()) {
|
|
158
|
+
mismatches.push({ path: relPath, expected: record.hash, actual });
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
if (mismatches.length > 0) {
|
|
162
|
+
return { status: "tampered", manifestPath, filesPinned: 0, mismatches };
|
|
163
|
+
}
|
|
164
|
+
return {
|
|
165
|
+
status: "verified",
|
|
166
|
+
manifestPath,
|
|
167
|
+
filesPinned: Object.keys(manifest.files).length,
|
|
168
|
+
mismatches: [],
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
// Fresh-pin mode: snap every cache file's hash + write manifest atomically.
|
|
172
|
+
const records = {};
|
|
173
|
+
const now = new Date().toISOString();
|
|
174
|
+
for (const rel of files) {
|
|
175
|
+
const full = `${cacheRoot.replace(/[\\/]+$/, "")}/${rel}`;
|
|
176
|
+
records[rel] = { hash: sha256File(full).toLowerCase(), pinnedAt: now };
|
|
177
|
+
}
|
|
178
|
+
const manifest = {
|
|
179
|
+
v: 1,
|
|
180
|
+
files: records,
|
|
181
|
+
pinnedByMnemeVersion: MNEME_VERSION_FOR_MANIFEST,
|
|
182
|
+
};
|
|
183
|
+
if (!existsSync(dirname(manifestPath))) {
|
|
184
|
+
mkdirSync(dirname(manifestPath), { recursive: true });
|
|
185
|
+
}
|
|
186
|
+
// Atomic temp+rename so a partial write can't poison the manifest.
|
|
187
|
+
const { renameSync, writeFileSync } = require("node:fs");
|
|
188
|
+
const tmp = `${manifestPath}.tmp`;
|
|
189
|
+
writeFileSync(tmp, JSON.stringify(manifest, null, 2), { encoding: "utf8", mode: 0o600 });
|
|
190
|
+
renameSync(tmp, manifestPath);
|
|
191
|
+
return {
|
|
192
|
+
status: "fresh-pin",
|
|
193
|
+
manifestPath,
|
|
194
|
+
filesPinned: Object.keys(records).length,
|
|
195
|
+
mismatches: [],
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
/** All-in-one helper: check the cache root against pinned checksums, if
|
|
199
|
+
* the user has set them. Throws on mismatch. No-op when unset. */
|
|
200
|
+
export function verifyAgainstPin(cacheRoot) {
|
|
201
|
+
const expected = readPinnedChecksums();
|
|
202
|
+
if (!expected)
|
|
203
|
+
return;
|
|
204
|
+
const result = verifyCache(cacheRoot, expected);
|
|
205
|
+
if (!result.ok) {
|
|
206
|
+
const lines = result.mismatches
|
|
207
|
+
.slice(0, 5)
|
|
208
|
+
.map((m) => ` ${m.path}\n expected: ${m.expected}\n actual: ${m.actual}`)
|
|
209
|
+
.join("\n");
|
|
210
|
+
throw new Error(`Bundled-model checksum verification FAILED — refusing to load possibly-tampered model.\n${lines}\n` +
|
|
211
|
+
`(${result.mismatches.length} mismatch${result.mismatches.length === 1 ? "" : "es"} total. ` +
|
|
212
|
+
`Set MNEME_PINNED_MODEL_CHECKSUMS to {} to disable, or update with the new hashes after auditing.)`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=checksum.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checksum.js","sourceRoot":"","sources":["../src/checksum.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checksum.test.d.ts","sourceRoot":"","sources":["../src/checksum.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* checksum — bundled-model integrity verification tests.
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
5
|
+
import { mkdtempSync, rmSync, writeFileSync, mkdirSync, readFileSync } from "node:fs";
|
|
6
|
+
import { tmpdir } from "node:os";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import { createHash } from "node:crypto";
|
|
9
|
+
import { sha256File, listFiles, verifyCache, readPinnedChecksums, verifyAgainstPin, tofuVerifyOrPin } from "./checksum.js";
|
|
10
|
+
let tmp;
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
tmp = mkdtempSync(join(tmpdir(), "mneme-checksum-"));
|
|
13
|
+
});
|
|
14
|
+
afterEach(() => {
|
|
15
|
+
delete process.env["MNEME_PINNED_MODEL_CHECKSUMS"];
|
|
16
|
+
try {
|
|
17
|
+
rmSync(tmp, { recursive: true, force: true });
|
|
18
|
+
}
|
|
19
|
+
catch { }
|
|
20
|
+
});
|
|
21
|
+
function expectedSha(content) {
|
|
22
|
+
return createHash("sha256").update(Buffer.from(content)).digest("hex");
|
|
23
|
+
}
|
|
24
|
+
describe("checksum — sha256File", () => {
|
|
25
|
+
it("hashes content deterministically", () => {
|
|
26
|
+
const p = join(tmp, "f.bin");
|
|
27
|
+
writeFileSync(p, "hello world");
|
|
28
|
+
expect(sha256File(p)).toBe(expectedSha("hello world"));
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
describe("checksum — listFiles", () => {
|
|
32
|
+
it("walks directory tree and returns relative paths", () => {
|
|
33
|
+
mkdirSync(join(tmp, "sub"), { recursive: true });
|
|
34
|
+
writeFileSync(join(tmp, "a.txt"), "1");
|
|
35
|
+
writeFileSync(join(tmp, "sub", "b.txt"), "2");
|
|
36
|
+
const list = listFiles(tmp).sort();
|
|
37
|
+
expect(list).toEqual(["a.txt", "sub/b.txt"]);
|
|
38
|
+
});
|
|
39
|
+
it("returns empty for missing dir", () => {
|
|
40
|
+
expect(listFiles(join(tmp, "nope"))).toEqual([]);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
describe("checksum — verifyCache", () => {
|
|
44
|
+
it("verifies all matching files", () => {
|
|
45
|
+
writeFileSync(join(tmp, "model.onnx"), "MODEL_BYTES");
|
|
46
|
+
const r = verifyCache(tmp, { "model.onnx": expectedSha("MODEL_BYTES") });
|
|
47
|
+
expect(r.ok).toBe(true);
|
|
48
|
+
expect(r.verified).toBe(1);
|
|
49
|
+
expect(r.mismatches).toEqual([]);
|
|
50
|
+
});
|
|
51
|
+
it("flags mismatch on tampered file", () => {
|
|
52
|
+
writeFileSync(join(tmp, "model.onnx"), "TAMPERED_BYTES");
|
|
53
|
+
const r = verifyCache(tmp, { "model.onnx": expectedSha("ORIGINAL_BYTES") });
|
|
54
|
+
expect(r.ok).toBe(false);
|
|
55
|
+
expect(r.mismatches.length).toBe(1);
|
|
56
|
+
expect(r.mismatches[0].path).toBe("model.onnx");
|
|
57
|
+
});
|
|
58
|
+
it("flags missing pinned file", () => {
|
|
59
|
+
const r = verifyCache(tmp, { "missing.onnx": "abc123" });
|
|
60
|
+
expect(r.ok).toBe(false);
|
|
61
|
+
expect(r.mismatches[0].actual).toBe("(missing)");
|
|
62
|
+
});
|
|
63
|
+
it("reports unexpected files (informational, doesn't fail)", () => {
|
|
64
|
+
writeFileSync(join(tmp, "pinned.onnx"), "P");
|
|
65
|
+
writeFileSync(join(tmp, "extra.bin"), "E");
|
|
66
|
+
const r = verifyCache(tmp, { "pinned.onnx": expectedSha("P") });
|
|
67
|
+
expect(r.ok).toBe(true);
|
|
68
|
+
expect(r.unexpected).toContain("extra.bin");
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
describe("checksum — readPinnedChecksums", () => {
|
|
72
|
+
it("returns null when env unset", () => {
|
|
73
|
+
expect(readPinnedChecksums()).toBeNull();
|
|
74
|
+
});
|
|
75
|
+
it("parses valid JSON object", () => {
|
|
76
|
+
process.env["MNEME_PINNED_MODEL_CHECKSUMS"] = JSON.stringify({ "a.onnx": "deadbeef" });
|
|
77
|
+
expect(readPinnedChecksums()).toEqual({ "a.onnx": "deadbeef" });
|
|
78
|
+
});
|
|
79
|
+
it("returns null for non-object JSON", () => {
|
|
80
|
+
process.env["MNEME_PINNED_MODEL_CHECKSUMS"] = "[]";
|
|
81
|
+
expect(readPinnedChecksums()).toBeNull();
|
|
82
|
+
});
|
|
83
|
+
it("returns null for malformed JSON", () => {
|
|
84
|
+
process.env["MNEME_PINNED_MODEL_CHECKSUMS"] = "not json";
|
|
85
|
+
expect(readPinnedChecksums()).toBeNull();
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
describe("checksum — TOFU (Trust On First Use)", () => {
|
|
89
|
+
it("first call snapshots all cache files into the manifest", () => {
|
|
90
|
+
writeFileSync(join(tmp, "model.onnx"), "REAL");
|
|
91
|
+
writeFileSync(join(tmp, "tokenizer.json"), "{}");
|
|
92
|
+
const manifest = join(tmp, ".manifest.json");
|
|
93
|
+
const r = tofuVerifyOrPin(tmp, manifest);
|
|
94
|
+
expect(r.status).toBe("fresh-pin");
|
|
95
|
+
expect(r.filesPinned).toBe(2);
|
|
96
|
+
expect(r.mismatches).toEqual([]);
|
|
97
|
+
// Manifest persists with v:1 schema
|
|
98
|
+
const m = JSON.parse(readFileSync(manifest, "utf8"));
|
|
99
|
+
expect(m.v).toBe(1);
|
|
100
|
+
expect(m.files["model.onnx"].hash).toBeDefined();
|
|
101
|
+
expect(m.files["tokenizer.json"].hash).toBeDefined();
|
|
102
|
+
expect(m.pinnedByMnemeVersion).toMatch(/^\d+\.\d+\.\d+/);
|
|
103
|
+
});
|
|
104
|
+
it("second call verifies (status=verified) when files unchanged", () => {
|
|
105
|
+
writeFileSync(join(tmp, "model.onnx"), "REAL");
|
|
106
|
+
const manifest = join(tmp, ".manifest.json");
|
|
107
|
+
tofuVerifyOrPin(tmp, manifest);
|
|
108
|
+
const r2 = tofuVerifyOrPin(tmp, manifest);
|
|
109
|
+
expect(r2.status).toBe("verified");
|
|
110
|
+
expect(r2.filesPinned).toBe(1);
|
|
111
|
+
expect(r2.mismatches).toEqual([]);
|
|
112
|
+
});
|
|
113
|
+
it("detects tampered file as status=tampered (no silent re-pin)", () => {
|
|
114
|
+
writeFileSync(join(tmp, "model.onnx"), "REAL");
|
|
115
|
+
const manifest = join(tmp, ".manifest.json");
|
|
116
|
+
tofuVerifyOrPin(tmp, manifest);
|
|
117
|
+
// Tamper after pinning
|
|
118
|
+
writeFileSync(join(tmp, "model.onnx"), "FAKE");
|
|
119
|
+
const r2 = tofuVerifyOrPin(tmp, manifest);
|
|
120
|
+
expect(r2.status).toBe("tampered");
|
|
121
|
+
expect(r2.mismatches.length).toBe(1);
|
|
122
|
+
expect(r2.mismatches[0].path).toBe("model.onnx");
|
|
123
|
+
});
|
|
124
|
+
it("detects missing pinned file", () => {
|
|
125
|
+
writeFileSync(join(tmp, "model.onnx"), "REAL");
|
|
126
|
+
const manifest = join(tmp, ".manifest.json");
|
|
127
|
+
tofuVerifyOrPin(tmp, manifest);
|
|
128
|
+
rmSync(join(tmp, "model.onnx"));
|
|
129
|
+
const r2 = tofuVerifyOrPin(tmp, manifest);
|
|
130
|
+
expect(r2.status).toBe("tampered");
|
|
131
|
+
expect(r2.mismatches[0].actual).toBe("(missing)");
|
|
132
|
+
});
|
|
133
|
+
it("returns no-files for empty cache", () => {
|
|
134
|
+
const r = tofuVerifyOrPin(tmp, join(tmp, ".manifest.json"));
|
|
135
|
+
expect(r.status).toBe("no-files");
|
|
136
|
+
expect(r.filesPinned).toBe(0);
|
|
137
|
+
});
|
|
138
|
+
it("treats corrupt manifest as tampered (refuses silent re-pin)", () => {
|
|
139
|
+
writeFileSync(join(tmp, "model.onnx"), "REAL");
|
|
140
|
+
const manifest = join(tmp, ".manifest.json");
|
|
141
|
+
writeFileSync(manifest, "this is not json");
|
|
142
|
+
const r = tofuVerifyOrPin(tmp, manifest);
|
|
143
|
+
expect(r.status).toBe("tampered");
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
describe("checksum — verifyAgainstPin (integration)", () => {
|
|
147
|
+
it("no-ops when pin unset", () => {
|
|
148
|
+
expect(() => verifyAgainstPin(tmp)).not.toThrow();
|
|
149
|
+
});
|
|
150
|
+
it("throws on mismatch", () => {
|
|
151
|
+
writeFileSync(join(tmp, "m.onnx"), "REAL");
|
|
152
|
+
process.env["MNEME_PINNED_MODEL_CHECKSUMS"] = JSON.stringify({ "m.onnx": expectedSha("FAKE") });
|
|
153
|
+
expect(() => verifyAgainstPin(tmp)).toThrow(/checksum verification FAILED/);
|
|
154
|
+
});
|
|
155
|
+
it("succeeds on match", () => {
|
|
156
|
+
writeFileSync(join(tmp, "m.onnx"), "REAL");
|
|
157
|
+
process.env["MNEME_PINNED_MODEL_CHECKSUMS"] = JSON.stringify({ "m.onnx": expectedSha("REAL") });
|
|
158
|
+
expect(() => verifyAgainstPin(tmp)).not.toThrow();
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
//# sourceMappingURL=checksum.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checksum.test.js","sourceRoot":"","sources":["../src/checksum.test.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC"}
|
package/dist/resolve.d.ts
CHANGED
|
@@ -19,6 +19,9 @@ export interface ResolveOptions {
|
|
|
19
19
|
baseUrl?: string;
|
|
20
20
|
/** Optional callback for bundled-model download progress. */
|
|
21
21
|
onBundledProgress?: NonNullable<ConstructorParameters<typeof BundledEmbedder>[0]>["onProgress"];
|
|
22
|
+
/** v1.11.1 — TOFU manifest path (per-repo, e.g. `<repo>/.mneme/model-checksums.json`).
|
|
23
|
+
* When provided, the bundled embedder pins/verifies the cache. */
|
|
24
|
+
tofuManifestPath?: string;
|
|
22
25
|
}
|
|
23
26
|
export declare function resolveEmbedder(opts?: ResolveOptions): Promise<EmbeddingProvider>;
|
|
24
27
|
/** Helper for callers that explicitly want the deterministic offline path. */
|
package/dist/resolve.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGxD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAG/C,MAAM,WAAW,cAAc;IAC7B;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,iBAAiB,CAAC,EAAE,WAAW,CAC7B,qBAAqB,CAAC,OAAO,eAAe,CAAC,CAAC,CAAC,CAAC,CACjD,CAAC,YAAY,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGxD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAG/C,MAAM,WAAW,cAAc;IAC7B;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,iBAAiB,CAAC,EAAE,WAAW,CAC7B,qBAAqB,CAAC,OAAO,eAAe,CAAC,CAAC,CAAC,CAAC,CACjD,CAAC,YAAY,CAAC,CAAC;IAChB;uEACmE;IACnE,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAsB,eAAe,CAAC,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAqE3F;AAED,8EAA8E;AAC9E,wBAAgB,YAAY,IAAI,iBAAiB,CAEhD"}
|
package/dist/resolve.js
CHANGED
|
@@ -19,7 +19,7 @@ export async function resolveEmbedder(opts = {}) {
|
|
|
19
19
|
throw new Error(`Ollama not reachable at ${opts.baseUrl ?? "http://127.0.0.1:11434"}. Start it with: ollama serve`);
|
|
20
20
|
}
|
|
21
21
|
if (provider === "bundled") {
|
|
22
|
-
return new BundledEmbedder({ model: opts.model, onProgress: opts.onBundledProgress });
|
|
22
|
+
return new BundledEmbedder({ model: opts.model, onProgress: opts.onBundledProgress, tofuManifestPath: opts.tofuManifestPath });
|
|
23
23
|
}
|
|
24
24
|
if (provider === "hash") {
|
|
25
25
|
return new HashEmbedder();
|
|
@@ -57,7 +57,7 @@ export async function resolveEmbedder(opts = {}) {
|
|
|
57
57
|
// first-run time budget.
|
|
58
58
|
// - if verify fails later (offline run on a fresh machine), the
|
|
59
59
|
// index command surfaces a clear error + suggests --embedder hash.
|
|
60
|
-
return new BundledEmbedder({ model: opts.model, onProgress: opts.onBundledProgress });
|
|
60
|
+
return new BundledEmbedder({ model: opts.model, onProgress: opts.onBundledProgress, tofuManifestPath: opts.tofuManifestPath });
|
|
61
61
|
// 4. Hash is the FINAL escape hatch — only chosen by explicit `--embedder
|
|
62
62
|
// hash` or by callers that don't want network/download. Auto-detect
|
|
63
63
|
// prefers bundled because it returns true semantic vectors with no setup.
|
package/dist/resolve.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mneme-ai/embeddings",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.17.2",
|
|
4
4
|
"description": "Embedding providers (OpenAI, Ollama, bundled-WASM, hash-fallback) for Mneme",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -34,6 +34,6 @@
|
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@huggingface/transformers": "^3.0.0",
|
|
37
|
-
"@mneme-ai/core": "1.
|
|
37
|
+
"@mneme-ai/core": "1.17.2"
|
|
38
38
|
}
|
|
39
39
|
}
|