@totalreclaw/totalreclaw 3.3.1-rc.8 → 3.3.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.
Files changed (81) hide show
  1. package/CHANGELOG.md +268 -1
  2. package/SKILL.md +29 -23
  3. package/api-client.ts +18 -11
  4. package/claims-helper.ts +47 -1
  5. package/config.ts +108 -4
  6. package/confirm-indexed.ts +191 -0
  7. package/crypto.ts +10 -2
  8. package/dist/api-client.js +226 -0
  9. package/dist/billing-cache.js +100 -0
  10. package/dist/claims-helper.js +624 -0
  11. package/dist/config.js +297 -0
  12. package/dist/confirm-indexed.js +127 -0
  13. package/dist/consolidation.js +258 -0
  14. package/dist/contradiction-sync.js +1034 -0
  15. package/dist/crypto.js +138 -0
  16. package/dist/digest-sync.js +361 -0
  17. package/dist/download-ux.js +63 -0
  18. package/dist/embedder-cache.js +185 -0
  19. package/dist/embedder-loader.js +121 -0
  20. package/dist/embedder-network.js +301 -0
  21. package/dist/embedding.js +141 -0
  22. package/dist/extractor.js +1225 -0
  23. package/dist/first-run.js +103 -0
  24. package/dist/fs-helpers.js +725 -0
  25. package/dist/gateway-url.js +197 -0
  26. package/dist/generate-mnemonic.js +13 -0
  27. package/dist/hot-cache-wrapper.js +101 -0
  28. package/dist/import-adapters/base-adapter.js +64 -0
  29. package/dist/import-adapters/chatgpt-adapter.js +238 -0
  30. package/dist/import-adapters/claude-adapter.js +114 -0
  31. package/dist/import-adapters/gemini-adapter.js +201 -0
  32. package/dist/import-adapters/index.js +26 -0
  33. package/dist/import-adapters/mcp-memory-adapter.js +219 -0
  34. package/dist/import-adapters/mem0-adapter.js +158 -0
  35. package/dist/import-adapters/types.js +1 -0
  36. package/dist/index.js +5388 -0
  37. package/dist/llm-client.js +687 -0
  38. package/dist/llm-profile-reader.js +346 -0
  39. package/dist/lsh.js +62 -0
  40. package/dist/onboarding-cli.js +750 -0
  41. package/dist/pair-cli.js +344 -0
  42. package/dist/pair-crypto.js +359 -0
  43. package/dist/pair-http.js +404 -0
  44. package/dist/pair-page.js +826 -0
  45. package/dist/pair-qr.js +107 -0
  46. package/dist/pair-remote-client.js +410 -0
  47. package/dist/pair-session-store.js +566 -0
  48. package/dist/pin.js +556 -0
  49. package/dist/qa-bug-report.js +301 -0
  50. package/dist/relay-headers.js +44 -0
  51. package/dist/reranker.js +409 -0
  52. package/dist/retype-setscope.js +368 -0
  53. package/dist/semantic-dedup.js +75 -0
  54. package/dist/subgraph-search.js +289 -0
  55. package/dist/subgraph-store.js +694 -0
  56. package/dist/tool-gating.js +58 -0
  57. package/download-ux.ts +91 -0
  58. package/embedder-cache.ts +230 -0
  59. package/embedder-loader.ts +189 -0
  60. package/embedder-network.ts +350 -0
  61. package/embedding.ts +118 -27
  62. package/fs-helpers.ts +277 -0
  63. package/gateway-url.ts +57 -9
  64. package/index.ts +469 -250
  65. package/llm-client.ts +4 -3
  66. package/lsh.ts +7 -2
  67. package/onboarding-cli.ts +114 -1
  68. package/package.json +24 -5
  69. package/pair-cli.ts +76 -8
  70. package/pair-crypto.ts +34 -24
  71. package/pair-page.ts +28 -17
  72. package/pair-qr.ts +152 -0
  73. package/pair-remote-client.ts +540 -0
  74. package/pin.ts +31 -0
  75. package/qa-bug-report.ts +84 -2
  76. package/relay-headers.ts +50 -0
  77. package/reranker.ts +40 -0
  78. package/retype-setscope.ts +69 -8
  79. package/skill.json +1 -1
  80. package/subgraph-search.ts +4 -3
  81. package/subgraph-store.ts +15 -10
@@ -0,0 +1,141 @@
1
+ /**
2
+ * TotalReclaw Plugin - Local Embedding via lazy GitHub-Releases bundle
3
+ *
4
+ * Generates text embeddings locally using an ONNX model. Preserves the
5
+ * E2EE guarantee — embeddings are computed on the user's machine and
6
+ * never leave it. The model itself, plus the heavy native dependencies
7
+ * (`@huggingface/transformers`, `onnxruntime-node`), is fetched on
8
+ * first use from a versioned GitHub Release tarball rather than shipped
9
+ * inside the npm/ClawHub plugin tarball.
10
+ *
11
+ * Why lazy retrieval (rc.22):
12
+ * rc.21 OOM-killed the OpenClaw gateway during `openclaw plugins install`
13
+ * on a 3.7 GB Hetzner VPS — the heavy native deps required ~700 MB+
14
+ * peak install RAM, and a partial install left orphaned
15
+ * `~/.openclaw/extensions/.openclaw-install-stage-*` directories that
16
+ * the loader then auto-discovered on every boot, crashing the CLI.
17
+ * rc.22 splits the heavy bits out of the install path: the plugin
18
+ * tarball stays ~5-10 MB (ClawHub-friendly), the model + native deps
19
+ * are downloaded lazily when the user actually invokes a memory tool,
20
+ * and per-turn OOM is recoverable in a way install-time OOM is not.
21
+ *
22
+ * Locked to Harrier-OSS-v1-270M (640d, q4, ~344MB, pre-pooled). Changing
23
+ * the embedding model breaks search across an existing vault, so the
24
+ * `TOTALRECLAW_EMBEDDING_MODEL` user-facing env var was removed in v1.
25
+ *
26
+ * Forward-compat (rc.22): every claim is tagged with `embedding_model_id`
27
+ * (see `getEmbeddingModelId()`) so a future distillation can be detected
28
+ * and rescoped per claim without breaking the active vault.
29
+ */
30
+ import os from 'node:os';
31
+ import path from 'node:path';
32
+ import { loadEmbedder } from './embedder-loader.js';
33
+ const HARRIER_MODEL = {
34
+ semanticId: 'harrier-oss-270m-q4',
35
+ hfId: 'onnx-community/harrier-oss-v1-270m-ONNX',
36
+ dims: 640,
37
+ pooling: 'sentence_embedding',
38
+ size: '~344MB',
39
+ dtype: 'q4',
40
+ };
41
+ function getModelConfig() {
42
+ return HARRIER_MODEL;
43
+ }
44
+ let runtimeConfig = null;
45
+ export function configureEmbedder(cfg) {
46
+ runtimeConfig = cfg;
47
+ }
48
+ /**
49
+ * Default cache root. Used when `configureEmbedder()` was not called —
50
+ * production code always calls it from index.ts; tests may rely on this
51
+ * default.
52
+ */
53
+ function defaultCacheRoot() {
54
+ return path.join(os.homedir(), '.totalreclaw', 'embedder');
55
+ }
56
+ function activeRuntimeConfig() {
57
+ if (runtimeConfig)
58
+ return runtimeConfig;
59
+ return { cacheRoot: defaultCacheRoot(), rcTag: '0.0.0-dev' };
60
+ }
61
+ /** Lazily initialized state. */
62
+ let pipelineExtractor = null;
63
+ let autoTokenizer = null;
64
+ let autoModel = null;
65
+ let activeModel = null;
66
+ /**
67
+ * Generate an embedding vector for the given text.
68
+ *
69
+ * On first call, downloads the embedder bundle (transformers + onnxruntime
70
+ * + the q4 ONNX model) from the pinned GitHub Release, verifies the
71
+ * tarball SHA-256 against the manifest, extracts to
72
+ * `~/.totalreclaw/embedder/v1/`, then loads the model into memory.
73
+ * Subsequent calls reuse the loaded model and run in ~100 ms.
74
+ */
75
+ export async function generateEmbedding(text, options) {
76
+ if (!activeModel) {
77
+ activeModel = getModelConfig();
78
+ const cfg = activeRuntimeConfig();
79
+ console.error(`[TotalReclaw] Embedding model first-call: fetching bundle ${activeModel.size} from GitHub Releases for v${cfg.rcTag} (cached at ${cfg.cacheRoot}).`);
80
+ const loaded = await loadEmbedder({
81
+ cacheRoot: cfg.cacheRoot,
82
+ rcTag: cfg.rcTag,
83
+ });
84
+ if (loaded.manifest.dimension !== activeModel.dims) {
85
+ throw new Error(`embedder bundle dimension ${loaded.manifest.dimension} does not match plugin-expected ${activeModel.dims}. ` +
86
+ `Refusing to use mismatched embedder — vector space drift would corrupt cosine search.`);
87
+ }
88
+ if (loaded.manifest.model_id !== activeModel.semanticId) {
89
+ console.error(`[TotalReclaw] WARNING: bundled model_id "${loaded.manifest.model_id}" != plugin-expected "${activeModel.semanticId}". Continuing — distillation forward-compat path.`);
90
+ }
91
+ // Resolve the transformers entrypoint via the cache-bound require.
92
+ // The bundled package was generated by `scripts/build-embedder-bundle.mjs`
93
+ // and lives at `<cache>/v1/node_modules/@huggingface/transformers`.
94
+ const transformers = loaded.cacheRequire('@huggingface/transformers');
95
+ const { AutoTokenizer, AutoModel, pipeline } = transformers;
96
+ if (activeModel.pooling === 'sentence_embedding') {
97
+ autoTokenizer = await AutoTokenizer.from_pretrained(activeModel.hfId);
98
+ autoModel = await AutoModel.from_pretrained(activeModel.hfId, {
99
+ dtype: activeModel.dtype,
100
+ });
101
+ }
102
+ else {
103
+ pipelineExtractor = await pipeline('feature-extraction', activeModel.hfId, {
104
+ dtype: activeModel.dtype,
105
+ });
106
+ }
107
+ console.error('[TotalReclaw] Embedding model ready. Future calls are in-memory.');
108
+ }
109
+ const model = activeModel;
110
+ if (model.pooling === 'sentence_embedding') {
111
+ const inputs = await autoTokenizer(text, { return_tensors: 'pt', padding: true });
112
+ const output = await autoModel(inputs);
113
+ return Array.from(output.sentence_embedding.data);
114
+ }
115
+ else {
116
+ const input = model.pooling === 'mean' && options?.isQuery
117
+ ? `query: ${text}`
118
+ : text;
119
+ const output = await pipelineExtractor(input, { pooling: model.pooling, normalize: true });
120
+ return Array.from(output.data);
121
+ }
122
+ }
123
+ /**
124
+ * Get the embedding vector dimensionality.
125
+ * Returns 640 for Harrier-OSS-270M-q4.
126
+ */
127
+ export function getEmbeddingDims() {
128
+ return getModelConfig().dims;
129
+ }
130
+ /**
131
+ * Get the semantic embedding-model id stamped on each new claim (rc.22+).
132
+ *
133
+ * Forward-compat marker: if a future plugin version distills to a smaller
134
+ * model, claims tagged with the prior id can be re-embedded selectively
135
+ * instead of forcing a vault-wide rebuild. Defaults to the v1 Harrier id —
136
+ * plugin code always tags new claims via this constant, never trusts the
137
+ * model id from a downloaded bundle for write-time tagging.
138
+ */
139
+ export function getEmbeddingModelId() {
140
+ return getModelConfig().semanticId;
141
+ }