@totalreclaw/totalreclaw 3.3.1-rc.14 → 3.3.1-rc.15
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/CHANGELOG.md +41 -0
- package/embedding.ts +40 -4
- package/package.json +14 -4
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,47 @@ All notable changes to `@totalreclaw/totalreclaw` (the OpenClaw plugin) are docu
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [3.3.1-rc.15] — 2026-04-24
|
|
8
|
+
|
|
9
|
+
Install-time unblock for bandwidth-constrained hosts. Lazy-loads the ONNX
|
|
10
|
+
runtime instead of forcing a ~216MB download during `openclaw plugins
|
|
11
|
+
install`.
|
|
12
|
+
|
|
13
|
+
### Lazy-loaded ONNX / `@huggingface/transformers`
|
|
14
|
+
|
|
15
|
+
`openclaw plugins install @totalreclaw/totalreclaw` on slow hosts (VPNs,
|
|
16
|
+
CI containers with limited bandwidth, metered connections) was exceeding
|
|
17
|
+
the plugin-install timeout mid-download and getting SIGTERM'd, leaving
|
|
18
|
+
the plugin partially installed. Root cause: `@huggingface/transformers`
|
|
19
|
+
was a direct `dependency`, which transitively pulled
|
|
20
|
+
`onnxruntime-node`'s postinstall binary fetch (~216MB from GitHub
|
|
21
|
+
Releases).
|
|
22
|
+
|
|
23
|
+
- `@huggingface/transformers` and `onnxruntime-node` moved from
|
|
24
|
+
`dependencies` to optional `peerDependencies`
|
|
25
|
+
(`peerDependenciesMeta.<name>.optional: true`). npm v7+ and the
|
|
26
|
+
OpenClaw install path (`--legacy-peer-deps`) both skip these by
|
|
27
|
+
default — plugin install is now lean.
|
|
28
|
+
- `embedding.ts` converts the static
|
|
29
|
+
`import { AutoTokenizer, AutoModel, pipeline } from
|
|
30
|
+
'@huggingface/transformers'` into a dynamic `await import(...)` on
|
|
31
|
+
the first `generateEmbedding` call. If the optional peer is missing,
|
|
32
|
+
the error surfaces a clear install hint:
|
|
33
|
+
`npm install @huggingface/transformers`.
|
|
34
|
+
- New regression test `lazy-load-embedding.test.ts` asserts the
|
|
35
|
+
invariants (no top-level static runtime import; heavy packages not in
|
|
36
|
+
`dependencies`; peer-dep `optional` flag set) so a future refactor
|
|
37
|
+
can't silently reintroduce the install-time block.
|
|
38
|
+
|
|
39
|
+
**User impact:** users on constrained hosts can now install the plugin
|
|
40
|
+
without the 216MB download. Users who want semantic memory (recall /
|
|
41
|
+
search over encrypted facts) install `@huggingface/transformers`
|
|
42
|
+
separately — one-time, resumable if it times out.
|
|
43
|
+
|
|
44
|
+
Fixes [issue #92][i92] (QA bug 6 of 10, split from #84).
|
|
45
|
+
|
|
46
|
+
[i92]: https://github.com/p-diogo/totalreclaw-internal/issues/92
|
|
47
|
+
|
|
7
48
|
## [3.3.1-rc.14] — 2026-04-24
|
|
8
49
|
|
|
9
50
|
Coordinated version bump with Python `2.3.1rc14`. Two narrow bug fixes
|
package/embedding.ts
CHANGED
|
@@ -8,11 +8,44 @@
|
|
|
8
8
|
* embedding model breaks search across an existing vault, so the
|
|
9
9
|
* `TOTALRECLAW_EMBEDDING_MODEL` user-facing env var was removed in v1.
|
|
10
10
|
*
|
|
11
|
-
* Dependencies: @huggingface/transformers
|
|
11
|
+
* Dependencies: @huggingface/transformers is declared as an optional peer
|
|
12
|
+
* dependency. It is lazy-loaded on the first `generateEmbedding` call so
|
|
13
|
+
* `openclaw plugins install @totalreclaw/totalreclaw` does not block on the
|
|
14
|
+
* ~216MB onnxruntime-node native-binary download. Install it separately to
|
|
15
|
+
* enable semantic search: `npm install @huggingface/transformers`.
|
|
12
16
|
*/
|
|
13
17
|
|
|
18
|
+
// Type-only import — erased at compile time, no runtime dep on the package.
|
|
14
19
|
// @ts-ignore - @huggingface/transformers types may not be perfect
|
|
15
|
-
import {
|
|
20
|
+
import type { FeatureExtractionPipeline } from '@huggingface/transformers';
|
|
21
|
+
|
|
22
|
+
type HFTransformers = typeof import('@huggingface/transformers');
|
|
23
|
+
|
|
24
|
+
/** Cached module handle after first successful dynamic import. */
|
|
25
|
+
let transformersModule: HFTransformers | null = null;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Lazily import @huggingface/transformers. The package is declared as an
|
|
29
|
+
* optional peer dependency so the plugin installs on bandwidth-constrained
|
|
30
|
+
* hosts without pulling the onnxruntime-node native binary (~216MB). On first
|
|
31
|
+
* use, try to load it; if the user never installed it, surface a clear
|
|
32
|
+
* actionable error with the install command.
|
|
33
|
+
*/
|
|
34
|
+
async function loadTransformers(): Promise<HFTransformers> {
|
|
35
|
+
if (transformersModule) return transformersModule;
|
|
36
|
+
try {
|
|
37
|
+
// @ts-ignore - dynamic import target is the optional peer dep
|
|
38
|
+
transformersModule = (await import('@huggingface/transformers')) as HFTransformers;
|
|
39
|
+
return transformersModule;
|
|
40
|
+
} catch (err) {
|
|
41
|
+
const hint =
|
|
42
|
+
'[TotalReclaw] @huggingface/transformers is not installed. ' +
|
|
43
|
+
'Semantic memory requires it (one-time ~216MB download of ONNX runtime + model). ' +
|
|
44
|
+
'Install with: npm install @huggingface/transformers';
|
|
45
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
46
|
+
throw new Error(`${hint}\nUnderlying load error: ${detail}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
16
49
|
|
|
17
50
|
interface ModelConfig {
|
|
18
51
|
id: string;
|
|
@@ -45,14 +78,17 @@ let activeModel: ModelConfig | null = null;
|
|
|
45
78
|
/**
|
|
46
79
|
* Generate an embedding vector for the given text.
|
|
47
80
|
*
|
|
48
|
-
* On first call,
|
|
49
|
-
*
|
|
81
|
+
* On first call, dynamically imports @huggingface/transformers (requires it
|
|
82
|
+
* to be installed — see module docstring) and downloads the ONNX model
|
|
83
|
+
* (cached after download). Subsequent calls reuse the loaded module + model
|
|
84
|
+
* and run in ~100ms.
|
|
50
85
|
*/
|
|
51
86
|
export async function generateEmbedding(
|
|
52
87
|
text: string,
|
|
53
88
|
options?: { isQuery?: boolean },
|
|
54
89
|
): Promise<number[]> {
|
|
55
90
|
if (!activeModel) {
|
|
91
|
+
const { AutoTokenizer, AutoModel, pipeline } = await loadTransformers();
|
|
56
92
|
activeModel = getModelConfig();
|
|
57
93
|
console.error(`[TotalReclaw] Downloading embedding model (${activeModel.size}, one-time setup)...`);
|
|
58
94
|
console.error('[TotalReclaw] This enables semantic search across your encrypted memories.');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@totalreclaw/totalreclaw",
|
|
3
|
-
"version": "3.3.1-rc.
|
|
3
|
+
"version": "3.3.1-rc.15",
|
|
4
4
|
"description": "End-to-end encrypted, agent-portable memory for OpenClaw and any LLM-agent runtime. XChaCha20-Poly1305 with protobuf v4 + on-chain Memory Taxonomy v1 (claim / preference / directive / commitment / episode / summary).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -31,16 +31,26 @@
|
|
|
31
31
|
"author": "TotalReclaw Team",
|
|
32
32
|
"license": "MIT",
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@huggingface/transformers": "^4.0.1",
|
|
35
34
|
"@totalreclaw/client": "^1.2.0",
|
|
36
35
|
"@totalreclaw/core": "^2.1.1",
|
|
37
36
|
"@types/qrcode": "^1.5.6",
|
|
38
37
|
"@types/ws": "^8.5.12",
|
|
39
|
-
"onnxruntime-node": "^1.24.0",
|
|
40
38
|
"qrcode": "^1.5.4",
|
|
41
39
|
"qrcode-terminal": "^0.12.0",
|
|
42
40
|
"ws": "^8.18.3"
|
|
43
41
|
},
|
|
42
|
+
"peerDependencies": {
|
|
43
|
+
"@huggingface/transformers": "^4.0.1",
|
|
44
|
+
"onnxruntime-node": "^1.24.0"
|
|
45
|
+
},
|
|
46
|
+
"peerDependenciesMeta": {
|
|
47
|
+
"@huggingface/transformers": {
|
|
48
|
+
"optional": true
|
|
49
|
+
},
|
|
50
|
+
"onnxruntime-node": {
|
|
51
|
+
"optional": true
|
|
52
|
+
}
|
|
53
|
+
},
|
|
44
54
|
"files": [
|
|
45
55
|
"*.ts",
|
|
46
56
|
"import-adapters/",
|
|
@@ -54,7 +64,7 @@
|
|
|
54
64
|
"skill.json"
|
|
55
65
|
],
|
|
56
66
|
"scripts": {
|
|
57
|
-
"test": "npx tsx manifest-shape.test.ts && npx tsx config-schema.test.ts && npx tsx llm-profile-reader.test.ts && npx tsx llm-client.test.ts && npx tsx llm-client-retry.test.ts && npx tsx gateway-url.test.ts && npx tsx retype-setscope.test.ts && npx tsx tool-gating.test.ts && npx tsx onboarding-noninteractive.test.ts && npx tsx pair-cli-json.test.ts && npx tsx pair-qr.test.ts && npx tsx pair-remote-client.test.ts && npx tsx qa-bug-report.test.ts && npx tsx nonce-serialization.test.ts && npx tsx phrase-safety-registry.test.ts",
|
|
67
|
+
"test": "npx tsx manifest-shape.test.ts && npx tsx config-schema.test.ts && npx tsx llm-profile-reader.test.ts && npx tsx llm-client.test.ts && npx tsx llm-client-retry.test.ts && npx tsx gateway-url.test.ts && npx tsx retype-setscope.test.ts && npx tsx tool-gating.test.ts && npx tsx onboarding-noninteractive.test.ts && npx tsx pair-cli-json.test.ts && npx tsx pair-qr.test.ts && npx tsx pair-remote-client.test.ts && npx tsx qa-bug-report.test.ts && npx tsx nonce-serialization.test.ts && npx tsx phrase-safety-registry.test.ts && npx tsx lazy-load-embedding.test.ts",
|
|
58
68
|
"check-scanner": "node ../scripts/check-scanner.mjs",
|
|
59
69
|
"prepublishOnly": "node ../scripts/check-scanner.mjs"
|
|
60
70
|
},
|