@totalreclaw/totalreclaw 3.3.12-rc.20 → 3.3.12-rc.22
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/SKILL.md +1 -1
- package/billing-cache.ts +49 -5
- package/config.ts +41 -1
- package/dist/billing-cache.js +37 -5
- package/dist/config.js +37 -1
- package/dist/index.js +23 -3
- package/dist/subgraph-store.js +11 -3
- package/dist/tr-cli.js +1 -1
- package/index.ts +26 -3
- package/package.json +2 -2
- package/skill.json +1 -1
- package/subgraph-store.ts +11 -3
- package/tr-cli.ts +1 -1
package/SKILL.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: totalreclaw
|
|
3
3
|
description: "End-to-end encrypted, decentralized memory for OpenClaw. A native kind:memory provider — recall is automatic via memory_search/memory_get, and facts are captured in the background. Trigger on 'install TotalReclaw', 'set up TotalReclaw', 'restore my recovery phrase', any recall request ('what do you remember about me', 'what's my X'), AND any explicit remember request ('remember X', 'save X')."
|
|
4
|
-
version: 3.3.12-rc.
|
|
4
|
+
version: 3.3.12-rc.22
|
|
5
5
|
author: TotalReclaw Team
|
|
6
6
|
license: MIT
|
|
7
7
|
homepage: https://totalreclaw.xyz
|
package/billing-cache.ts
CHANGED
|
@@ -14,6 +14,9 @@
|
|
|
14
14
|
* - keeps the chain-id override in sync with the relay's authoritative
|
|
15
15
|
* `chain_id` (after ops-1 both tiers are on Gnosis 100; the client consumes
|
|
16
16
|
* the relay value verbatim — see `syncChainIdFromBilling`)
|
|
17
|
+
* - keeps the DataEdge-address override in sync with the relay's
|
|
18
|
+
* authoritative `data_edge_address` (staging vs prod contract; consumed
|
|
19
|
+
* verbatim — see `syncDataEdgeAddressFromBilling`, #460)
|
|
17
20
|
* - does NOT import anything that performs outbound I/O
|
|
18
21
|
*
|
|
19
22
|
* Do NOT add any outbound-request call to this file — a single match for
|
|
@@ -24,7 +27,10 @@
|
|
|
24
27
|
|
|
25
28
|
import fs from 'node:fs';
|
|
26
29
|
import path from 'node:path';
|
|
27
|
-
import { CONFIG, setChainIdOverride } from './config.js';
|
|
30
|
+
import { CONFIG, setChainIdOverride, setDataEdgeAddressOverride } from './config.js';
|
|
31
|
+
|
|
32
|
+
/** A plausible EVM address — anything else from billing is ignored (#460). */
|
|
33
|
+
const DATA_EDGE_ADDRESS_RE = /^0x[0-9a-fA-F]{40}$/;
|
|
28
34
|
|
|
29
35
|
// ---------------------------------------------------------------------------
|
|
30
36
|
// Constants
|
|
@@ -57,6 +63,13 @@ export interface BillingCache {
|
|
|
57
63
|
* source of truth, so the client consumes this verbatim (#402).
|
|
58
64
|
*/
|
|
59
65
|
chain_id?: number;
|
|
66
|
+
/**
|
|
67
|
+
* Authoritative DataEdge contract address from the relay
|
|
68
|
+
* `/v1/billing/status` response. Staging returns the isolated staging
|
|
69
|
+
* DataEdge, production the prod DataEdge; the client consumes this verbatim
|
|
70
|
+
* so writes and reads land on the same contract (#460).
|
|
71
|
+
*/
|
|
72
|
+
data_edge_address?: string;
|
|
60
73
|
checked_at: number;
|
|
61
74
|
}
|
|
62
75
|
|
|
@@ -82,6 +95,34 @@ export function syncChainIdFromBilling(chainId: number | undefined): void {
|
|
|
82
95
|
setChainIdOverride(typeof chainId === 'number' && Number.isFinite(chainId) ? chainId : 100);
|
|
83
96
|
}
|
|
84
97
|
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
// DataEdge-address sync
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Apply the relay's authoritative `data_edge_address` to the runtime DataEdge
|
|
104
|
+
* override. Mirrors `syncChainIdFromBilling`.
|
|
105
|
+
*
|
|
106
|
+
* The relay routes each environment to its own DataEdge (staging is on-chain
|
|
107
|
+
* isolated). If the client ignores this and uses the WASM-baked default (the
|
|
108
|
+
* PROD DataEdge), writes against the staging relay mine on the prod contract
|
|
109
|
+
* while reads come from the staging subgraph → empty recall + phantom
|
|
110
|
+
* "stored=N" success (#460).
|
|
111
|
+
*
|
|
112
|
+
* A missing / malformed `data_edge_address` (older relay, partial payload,
|
|
113
|
+
* junk) clears the override (`null`) so resolution falls through to the WASM
|
|
114
|
+
* default — never a stale value. Only a plausible address
|
|
115
|
+
* (`0x` + 40 hex) is honored. Called from `readBillingCache` and
|
|
116
|
+
* `writeBillingCache` so every cache read or write keeps the override in sync.
|
|
117
|
+
* Idempotent. The explicit env override (`TOTALRECLAW_DATA_EDGE_ADDRESS`)
|
|
118
|
+
* still wins — it is the first term in `getSubgraphConfig`.
|
|
119
|
+
*/
|
|
120
|
+
export function syncDataEdgeAddressFromBilling(address: string | undefined): void {
|
|
121
|
+
setDataEdgeAddressOverride(
|
|
122
|
+
typeof address === 'string' && DATA_EDGE_ADDRESS_RE.test(address) ? address : null,
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
85
126
|
// ---------------------------------------------------------------------------
|
|
86
127
|
// Read / write
|
|
87
128
|
// ---------------------------------------------------------------------------
|
|
@@ -99,9 +140,10 @@ export function readBillingCache(): BillingCache | null {
|
|
|
99
140
|
if (!fs.existsSync(BILLING_CACHE_PATH)) return null;
|
|
100
141
|
const raw = JSON.parse(fs.readFileSync(BILLING_CACHE_PATH, 'utf-8')) as BillingCache;
|
|
101
142
|
if (!raw.checked_at || Date.now() - raw.checked_at > BILLING_CACHE_TTL) return null;
|
|
102
|
-
// Keep chain
|
|
103
|
-
// across process restarts.
|
|
143
|
+
// Keep chain + DataEdge overrides in sync with the persisted authoritative
|
|
144
|
+
// values across process restarts.
|
|
104
145
|
syncChainIdFromBilling(raw.chain_id);
|
|
146
|
+
syncDataEdgeAddressFromBilling(raw.data_edge_address);
|
|
105
147
|
return raw;
|
|
106
148
|
} catch {
|
|
107
149
|
return null;
|
|
@@ -121,7 +163,9 @@ export function writeBillingCache(cache: BillingCache): void {
|
|
|
121
163
|
} catch {
|
|
122
164
|
// Best-effort — don't block on cache write failure.
|
|
123
165
|
}
|
|
124
|
-
// Sync chain
|
|
125
|
-
//
|
|
166
|
+
// Sync chain + DataEdge overrides AFTER the write so in-process UserOp
|
|
167
|
+
// signing + subgraph reads pick up the correct chain and contract
|
|
168
|
+
// immediately, even if the disk write failed.
|
|
126
169
|
syncChainIdFromBilling(cache.chain_id);
|
|
170
|
+
syncDataEdgeAddressFromBilling(cache.data_edge_address);
|
|
127
171
|
}
|
package/config.ts
CHANGED
|
@@ -122,6 +122,39 @@ export function __resetChainIdOverrideForTests(): void {
|
|
|
122
122
|
_chainIdOverride = null;
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
+
/**
|
|
126
|
+
* Runtime override for the DataEdge contract address, set after the relay
|
|
127
|
+
* billing response is read. The relay returns an authoritative
|
|
128
|
+
* `data_edge_address` in `/v1/billing/status` (staging routes to the isolated
|
|
129
|
+
* staging DataEdge, production to the prod DataEdge). Chain-aware clients MUST
|
|
130
|
+
* consume it verbatim — otherwise writes mine on the WASM-baked prod DataEdge
|
|
131
|
+
* while reads hit the relay's subgraph, so recall silently returns empty
|
|
132
|
+
* against staging (#460). Mirrors `_chainIdOverride`.
|
|
133
|
+
*
|
|
134
|
+
* `null` means "no billing override" → fall through to the WASM default. The
|
|
135
|
+
* explicit operator env override (`TOTALRECLAW_DATA_EDGE_ADDRESS`, exposed as
|
|
136
|
+
* `CONFIG.dataEdgeAddress`) always wins over this.
|
|
137
|
+
*/
|
|
138
|
+
let _dataEdgeAddressOverride: string | null = null;
|
|
139
|
+
|
|
140
|
+
export function setDataEdgeAddressOverride(address: string | null): void {
|
|
141
|
+
_dataEdgeAddressOverride = address;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Read the billing-sourced DataEdge override (or `''` when unset). Used by
|
|
146
|
+
* `getSubgraphConfig` as the middle term of the env → billing → WASM-default
|
|
147
|
+
* resolution order (#460).
|
|
148
|
+
*/
|
|
149
|
+
export function getDataEdgeAddressOverride(): string {
|
|
150
|
+
return _dataEdgeAddressOverride ?? '';
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/** Reset the DataEdge override — used by tests. */
|
|
154
|
+
export function __resetDataEdgeAddressOverrideForTests(): void {
|
|
155
|
+
_dataEdgeAddressOverride = null;
|
|
156
|
+
}
|
|
157
|
+
|
|
125
158
|
export const CONFIG = {
|
|
126
159
|
// Core — recoveryPhrase reads from override first, then env var.
|
|
127
160
|
// Use getRecoveryPhrase() for dynamic access; this property is for
|
|
@@ -235,7 +268,14 @@ export const CONFIG = {
|
|
|
235
268
|
get chainId(): number {
|
|
236
269
|
return _chainIdOverride ?? 100;
|
|
237
270
|
},
|
|
238
|
-
|
|
271
|
+
// Explicit operator env override for the DataEdge contract. Stays env-only:
|
|
272
|
+
// it is the FIRST term of `getSubgraphConfig`'s env → billing → WASM-default
|
|
273
|
+
// resolution order, so it wins over the relay's authoritative
|
|
274
|
+
// `data_edge_address` (see `getDataEdgeAddressOverride` / #460). Getter, not
|
|
275
|
+
// a literal, so it reflects the live env rather than freezing at module load.
|
|
276
|
+
get dataEdgeAddress(): string {
|
|
277
|
+
return process.env.TOTALRECLAW_DATA_EDGE_ADDRESS || '';
|
|
278
|
+
},
|
|
239
279
|
entryPointAddress: process.env.TOTALRECLAW_ENTRYPOINT_ADDRESS || '',
|
|
240
280
|
rpcUrl: process.env.TOTALRECLAW_RPC_URL || '',
|
|
241
281
|
|
package/dist/billing-cache.js
CHANGED
|
@@ -14,6 +14,9 @@
|
|
|
14
14
|
* - keeps the chain-id override in sync with the relay's authoritative
|
|
15
15
|
* `chain_id` (after ops-1 both tiers are on Gnosis 100; the client consumes
|
|
16
16
|
* the relay value verbatim — see `syncChainIdFromBilling`)
|
|
17
|
+
* - keeps the DataEdge-address override in sync with the relay's
|
|
18
|
+
* authoritative `data_edge_address` (staging vs prod contract; consumed
|
|
19
|
+
* verbatim — see `syncDataEdgeAddressFromBilling`, #460)
|
|
17
20
|
* - does NOT import anything that performs outbound I/O
|
|
18
21
|
*
|
|
19
22
|
* Do NOT add any outbound-request call to this file — a single match for
|
|
@@ -23,7 +26,9 @@
|
|
|
23
26
|
*/
|
|
24
27
|
import fs from 'node:fs';
|
|
25
28
|
import path from 'node:path';
|
|
26
|
-
import { CONFIG, setChainIdOverride } from './config.js';
|
|
29
|
+
import { CONFIG, setChainIdOverride, setDataEdgeAddressOverride } from './config.js';
|
|
30
|
+
/** A plausible EVM address — anything else from billing is ignored (#460). */
|
|
31
|
+
const DATA_EDGE_ADDRESS_RE = /^0x[0-9a-fA-F]{40}$/;
|
|
27
32
|
// ---------------------------------------------------------------------------
|
|
28
33
|
// Constants
|
|
29
34
|
// ---------------------------------------------------------------------------
|
|
@@ -51,6 +56,30 @@ export function syncChainIdFromBilling(chainId) {
|
|
|
51
56
|
setChainIdOverride(typeof chainId === 'number' && Number.isFinite(chainId) ? chainId : 100);
|
|
52
57
|
}
|
|
53
58
|
// ---------------------------------------------------------------------------
|
|
59
|
+
// DataEdge-address sync
|
|
60
|
+
// ---------------------------------------------------------------------------
|
|
61
|
+
/**
|
|
62
|
+
* Apply the relay's authoritative `data_edge_address` to the runtime DataEdge
|
|
63
|
+
* override. Mirrors `syncChainIdFromBilling`.
|
|
64
|
+
*
|
|
65
|
+
* The relay routes each environment to its own DataEdge (staging is on-chain
|
|
66
|
+
* isolated). If the client ignores this and uses the WASM-baked default (the
|
|
67
|
+
* PROD DataEdge), writes against the staging relay mine on the prod contract
|
|
68
|
+
* while reads come from the staging subgraph → empty recall + phantom
|
|
69
|
+
* "stored=N" success (#460).
|
|
70
|
+
*
|
|
71
|
+
* A missing / malformed `data_edge_address` (older relay, partial payload,
|
|
72
|
+
* junk) clears the override (`null`) so resolution falls through to the WASM
|
|
73
|
+
* default — never a stale value. Only a plausible address
|
|
74
|
+
* (`0x` + 40 hex) is honored. Called from `readBillingCache` and
|
|
75
|
+
* `writeBillingCache` so every cache read or write keeps the override in sync.
|
|
76
|
+
* Idempotent. The explicit env override (`TOTALRECLAW_DATA_EDGE_ADDRESS`)
|
|
77
|
+
* still wins — it is the first term in `getSubgraphConfig`.
|
|
78
|
+
*/
|
|
79
|
+
export function syncDataEdgeAddressFromBilling(address) {
|
|
80
|
+
setDataEdgeAddressOverride(typeof address === 'string' && DATA_EDGE_ADDRESS_RE.test(address) ? address : null);
|
|
81
|
+
}
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
54
83
|
// Read / write
|
|
55
84
|
// ---------------------------------------------------------------------------
|
|
56
85
|
/**
|
|
@@ -68,9 +97,10 @@ export function readBillingCache() {
|
|
|
68
97
|
const raw = JSON.parse(fs.readFileSync(BILLING_CACHE_PATH, 'utf-8'));
|
|
69
98
|
if (!raw.checked_at || Date.now() - raw.checked_at > BILLING_CACHE_TTL)
|
|
70
99
|
return null;
|
|
71
|
-
// Keep chain
|
|
72
|
-
// across process restarts.
|
|
100
|
+
// Keep chain + DataEdge overrides in sync with the persisted authoritative
|
|
101
|
+
// values across process restarts.
|
|
73
102
|
syncChainIdFromBilling(raw.chain_id);
|
|
103
|
+
syncDataEdgeAddressFromBilling(raw.data_edge_address);
|
|
74
104
|
return raw;
|
|
75
105
|
}
|
|
76
106
|
catch {
|
|
@@ -92,7 +122,9 @@ export function writeBillingCache(cache) {
|
|
|
92
122
|
catch {
|
|
93
123
|
// Best-effort — don't block on cache write failure.
|
|
94
124
|
}
|
|
95
|
-
// Sync chain
|
|
96
|
-
//
|
|
125
|
+
// Sync chain + DataEdge overrides AFTER the write so in-process UserOp
|
|
126
|
+
// signing + subgraph reads pick up the correct chain and contract
|
|
127
|
+
// immediately, even if the disk write failed.
|
|
97
128
|
syncChainIdFromBilling(cache.chain_id);
|
|
129
|
+
syncDataEdgeAddressFromBilling(cache.data_edge_address);
|
|
98
130
|
}
|
package/dist/config.js
CHANGED
|
@@ -107,6 +107,35 @@ export function setChainIdOverride(chainId) {
|
|
|
107
107
|
export function __resetChainIdOverrideForTests() {
|
|
108
108
|
_chainIdOverride = null;
|
|
109
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* Runtime override for the DataEdge contract address, set after the relay
|
|
112
|
+
* billing response is read. The relay returns an authoritative
|
|
113
|
+
* `data_edge_address` in `/v1/billing/status` (staging routes to the isolated
|
|
114
|
+
* staging DataEdge, production to the prod DataEdge). Chain-aware clients MUST
|
|
115
|
+
* consume it verbatim — otherwise writes mine on the WASM-baked prod DataEdge
|
|
116
|
+
* while reads hit the relay's subgraph, so recall silently returns empty
|
|
117
|
+
* against staging (#460). Mirrors `_chainIdOverride`.
|
|
118
|
+
*
|
|
119
|
+
* `null` means "no billing override" → fall through to the WASM default. The
|
|
120
|
+
* explicit operator env override (`TOTALRECLAW_DATA_EDGE_ADDRESS`, exposed as
|
|
121
|
+
* `CONFIG.dataEdgeAddress`) always wins over this.
|
|
122
|
+
*/
|
|
123
|
+
let _dataEdgeAddressOverride = null;
|
|
124
|
+
export function setDataEdgeAddressOverride(address) {
|
|
125
|
+
_dataEdgeAddressOverride = address;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Read the billing-sourced DataEdge override (or `''` when unset). Used by
|
|
129
|
+
* `getSubgraphConfig` as the middle term of the env → billing → WASM-default
|
|
130
|
+
* resolution order (#460).
|
|
131
|
+
*/
|
|
132
|
+
export function getDataEdgeAddressOverride() {
|
|
133
|
+
return _dataEdgeAddressOverride ?? '';
|
|
134
|
+
}
|
|
135
|
+
/** Reset the DataEdge override — used by tests. */
|
|
136
|
+
export function __resetDataEdgeAddressOverrideForTests() {
|
|
137
|
+
_dataEdgeAddressOverride = null;
|
|
138
|
+
}
|
|
110
139
|
export const CONFIG = {
|
|
111
140
|
// Core — recoveryPhrase reads from override first, then env var.
|
|
112
141
|
// Use getRecoveryPhrase() for dynamic access; this property is for
|
|
@@ -216,7 +245,14 @@ export const CONFIG = {
|
|
|
216
245
|
get chainId() {
|
|
217
246
|
return _chainIdOverride ?? 100;
|
|
218
247
|
},
|
|
219
|
-
|
|
248
|
+
// Explicit operator env override for the DataEdge contract. Stays env-only:
|
|
249
|
+
// it is the FIRST term of `getSubgraphConfig`'s env → billing → WASM-default
|
|
250
|
+
// resolution order, so it wins over the relay's authoritative
|
|
251
|
+
// `data_edge_address` (see `getDataEdgeAddressOverride` / #460). Getter, not
|
|
252
|
+
// a literal, so it reflects the live env rather than freezing at module load.
|
|
253
|
+
get dataEdgeAddress() {
|
|
254
|
+
return process.env.TOTALRECLAW_DATA_EDGE_ADDRESS || '';
|
|
255
|
+
},
|
|
220
256
|
entryPointAddress: process.env.TOTALRECLAW_ENTRYPOINT_ADDRESS || '',
|
|
221
257
|
rpcUrl: process.env.TOTALRECLAW_RPC_URL || '',
|
|
222
258
|
// 3.3.3-rc.1 (issue #187 — ONNX decouple): kill switch for the
|
package/dist/index.js
CHANGED
|
@@ -735,14 +735,15 @@ async function initialize(logger) {
|
|
|
735
735
|
const tier = billingData.tier;
|
|
736
736
|
const expiresAt = billingData.expires_at;
|
|
737
737
|
// Populate billing cache for future use. Copy the relay's
|
|
738
|
-
// authoritative chain_id so
|
|
739
|
-
// chain
|
|
738
|
+
// authoritative chain_id + data_edge_address so they land on disk and
|
|
739
|
+
// drive the runtime chain + DataEdge overrides verbatim (#402, #460).
|
|
740
740
|
writeBillingCache({
|
|
741
741
|
tier: tier || 'free',
|
|
742
742
|
free_writes_used: billingData.free_writes_used ?? 0,
|
|
743
743
|
free_writes_limit: billingData.free_writes_limit ?? 0,
|
|
744
744
|
features: billingData.features,
|
|
745
745
|
chain_id: billingData.chain_id,
|
|
746
|
+
data_edge_address: billingData.data_edge_address,
|
|
746
747
|
checked_at: Date.now(),
|
|
747
748
|
});
|
|
748
749
|
if (tier === 'pro' && expiresAt) {
|
|
@@ -3300,7 +3301,24 @@ const plugin = {
|
|
|
3300
3301
|
// JSON output: every subcommand accepts --json and emits a single
|
|
3301
3302
|
// machine-parseable JSON line on stdout (agent-driven use). Plain
|
|
3302
3303
|
// text is for direct user CLI use.
|
|
3303
|
-
//
|
|
3304
|
+
//
|
|
3305
|
+
// rc.20 (#402): the import/upgrade wiring below referenced a bare
|
|
3306
|
+
// `tr` that was never declared in THIS callback scope —
|
|
3307
|
+
// registerOnboardingCli and registerPairCli each declare their own
|
|
3308
|
+
// LOCAL `tr`, invisible here. That undeclared reference threw
|
|
3309
|
+
// `ReferenceError: tr is not defined` the moment OpenClaw ran the
|
|
3310
|
+
// callback, killing EVERY `openclaw totalreclaw <sub>` command
|
|
3311
|
+
// (dead since the 3.3.13 import/upgrade restoration; shipped in
|
|
3312
|
+
// rc.19 + rc.20). The build is `tsc --noCheck`, so the type checker
|
|
3313
|
+
// never caught it. Resolve the command group the same way
|
|
3314
|
+
// registerPairCli does — registerOnboardingCli always created it, so
|
|
3315
|
+
// this find() succeeds; the guard is belt-and-braces.
|
|
3316
|
+
const tr = program.commands.find((c) => c.name() === 'totalreclaw');
|
|
3317
|
+
if (!tr) {
|
|
3318
|
+
api.logger.warn('TotalReclaw: `totalreclaw` CLI group not found after onboarding/pair registration — ' +
|
|
3319
|
+
'skipping import/upgrade wiring. `openclaw totalreclaw import`/`upgrade` will be unavailable.');
|
|
3320
|
+
return;
|
|
3321
|
+
}
|
|
3304
3322
|
const importCmd = tr.command('import')
|
|
3305
3323
|
.description('Import memories from another tool (Mem0, MCP Memory, ChatGPT, Claude, Gemini). ' +
|
|
3306
3324
|
'Subcommands: `import status`, `import abort`.');
|
|
@@ -4066,6 +4084,8 @@ const plugin = {
|
|
|
4066
4084
|
features: billingData.features,
|
|
4067
4085
|
// Relay's authoritative chain_id → drives the chain override verbatim (#402).
|
|
4068
4086
|
chain_id: billingData.chain_id,
|
|
4087
|
+
// Relay's authoritative data_edge_address → drives the DataEdge override verbatim (#460).
|
|
4088
|
+
data_edge_address: billingData.data_edge_address,
|
|
4069
4089
|
checked_at: Date.now(),
|
|
4070
4090
|
};
|
|
4071
4091
|
writeBillingCache(cache);
|
package/dist/subgraph-store.js
CHANGED
|
@@ -21,7 +21,7 @@ function getWasm() {
|
|
|
21
21
|
_wasm = requireWasm('@totalreclaw/core');
|
|
22
22
|
return _wasm;
|
|
23
23
|
}
|
|
24
|
-
import { CONFIG } from './config.js';
|
|
24
|
+
import { CONFIG, getDataEdgeAddressOverride } from './config.js';
|
|
25
25
|
import { buildRelayHeaders } from './relay-headers.js';
|
|
26
26
|
import { rpcRequest, rpcWithRetry } from './relay.js';
|
|
27
27
|
import { signUserOp } from './vault-crypto.js';
|
|
@@ -712,7 +712,10 @@ export function isSubgraphMode() {
|
|
|
712
712
|
* - TOTALRECLAW_SELF_HOSTED -- set "true" to use self-hosted server (default: managed service)
|
|
713
713
|
*
|
|
714
714
|
* Chain ID is no longer configurable via env — it is auto-detected from the
|
|
715
|
-
* relay billing response (
|
|
715
|
+
* relay billing response (post-ops-1 both tiers are on Gnosis mainnet, chain
|
|
716
|
+
* 100). The DataEdge contract address is likewise consumed from the relay's
|
|
717
|
+
* authoritative `data_edge_address` (env override still wins, WASM default is
|
|
718
|
+
* the final fallback — see the `dataEdgeAddress` resolution below, #460).
|
|
716
719
|
*/
|
|
717
720
|
export function getSubgraphConfig() {
|
|
718
721
|
return {
|
|
@@ -721,7 +724,12 @@ export function getSubgraphConfig() {
|
|
|
721
724
|
mnemonic: CONFIG.recoveryPhrase,
|
|
722
725
|
cachePath: CONFIG.cachePath,
|
|
723
726
|
chainId: CONFIG.chainId,
|
|
724
|
-
|
|
727
|
+
// Resolution order (#460): explicit operator env override → relay billing
|
|
728
|
+
// `data_edge_address` (verbatim) → WASM-baked default. The relay routes
|
|
729
|
+
// each environment to its own DataEdge (staging is on-chain isolated), so
|
|
730
|
+
// consuming its value keeps writes + reads on the same contract; without
|
|
731
|
+
// the middle term staging writes mined on the prod default → empty recall.
|
|
732
|
+
dataEdgeAddress: CONFIG.dataEdgeAddress || getDataEdgeAddressOverride() || getWasm().getDataEdgeAddress(),
|
|
725
733
|
entryPointAddress: CONFIG.entryPointAddress || getWasm().getEntryPointAddress(),
|
|
726
734
|
rpcUrl: CONFIG.rpcUrl || undefined,
|
|
727
735
|
};
|
package/dist/tr-cli.js
CHANGED
|
@@ -51,7 +51,7 @@ const STATE_PATH = CONFIG.onboardingStatePath;
|
|
|
51
51
|
// Auto-synced by skill/scripts/sync-version.mjs from skill/plugin/package.json::version.
|
|
52
52
|
// Do not edit by hand — running tests will catch drift but the publish workflow
|
|
53
53
|
// rewrites this constant at the start of every npm/ClawHub publish.
|
|
54
|
-
const PLUGIN_VERSION = '3.3.12-rc.
|
|
54
|
+
const PLUGIN_VERSION = '3.3.12-rc.22';
|
|
55
55
|
function die(msg, code = 1) {
|
|
56
56
|
process.stderr.write(`tr: ${msg}\n`);
|
|
57
57
|
process.exit(code);
|
package/index.ts
CHANGED
|
@@ -1007,14 +1007,15 @@ async function initialize(logger: OpenClawPluginApi['logger']): Promise<void> {
|
|
|
1007
1007
|
const tier = billingData.tier as string;
|
|
1008
1008
|
const expiresAt = billingData.expires_at as string | undefined;
|
|
1009
1009
|
// Populate billing cache for future use. Copy the relay's
|
|
1010
|
-
// authoritative chain_id so
|
|
1011
|
-
// chain
|
|
1010
|
+
// authoritative chain_id + data_edge_address so they land on disk and
|
|
1011
|
+
// drive the runtime chain + DataEdge overrides verbatim (#402, #460).
|
|
1012
1012
|
writeBillingCache({
|
|
1013
1013
|
tier: tier || 'free',
|
|
1014
1014
|
free_writes_used: (billingData.free_writes_used as number) ?? 0,
|
|
1015
1015
|
free_writes_limit: (billingData.free_writes_limit as number) ?? 0,
|
|
1016
1016
|
features: billingData.features as BillingCache['features'] | undefined,
|
|
1017
1017
|
chain_id: billingData.chain_id as number | undefined,
|
|
1018
|
+
data_edge_address: billingData.data_edge_address as string | undefined,
|
|
1018
1019
|
checked_at: Date.now(),
|
|
1019
1020
|
});
|
|
1020
1021
|
if (tier === 'pro' && expiresAt) {
|
|
@@ -3943,7 +3944,27 @@ const plugin = {
|
|
|
3943
3944
|
// JSON output: every subcommand accepts --json and emits a single
|
|
3944
3945
|
// machine-parseable JSON line on stdout (agent-driven use). Plain
|
|
3945
3946
|
// text is for direct user CLI use.
|
|
3946
|
-
//
|
|
3947
|
+
//
|
|
3948
|
+
// rc.20 (#402): the import/upgrade wiring below referenced a bare
|
|
3949
|
+
// `tr` that was never declared in THIS callback scope —
|
|
3950
|
+
// registerOnboardingCli and registerPairCli each declare their own
|
|
3951
|
+
// LOCAL `tr`, invisible here. That undeclared reference threw
|
|
3952
|
+
// `ReferenceError: tr is not defined` the moment OpenClaw ran the
|
|
3953
|
+
// callback, killing EVERY `openclaw totalreclaw <sub>` command
|
|
3954
|
+
// (dead since the 3.3.13 import/upgrade restoration; shipped in
|
|
3955
|
+
// rc.19 + rc.20). The build is `tsc --noCheck`, so the type checker
|
|
3956
|
+
// never caught it. Resolve the command group the same way
|
|
3957
|
+
// registerPairCli does — registerOnboardingCli always created it, so
|
|
3958
|
+
// this find() succeeds; the guard is belt-and-braces.
|
|
3959
|
+
const tr = program.commands.find((c: any) => c.name() === 'totalreclaw');
|
|
3960
|
+
if (!tr) {
|
|
3961
|
+
api.logger.warn(
|
|
3962
|
+
'TotalReclaw: `totalreclaw` CLI group not found after onboarding/pair registration — ' +
|
|
3963
|
+
'skipping import/upgrade wiring. `openclaw totalreclaw import`/`upgrade` will be unavailable.',
|
|
3964
|
+
);
|
|
3965
|
+
return;
|
|
3966
|
+
}
|
|
3967
|
+
|
|
3947
3968
|
const importCmd = tr.command('import')
|
|
3948
3969
|
.description(
|
|
3949
3970
|
'Import memories from another tool (Mem0, MCP Memory, ChatGPT, Claude, Gemini). ' +
|
|
@@ -4765,6 +4786,8 @@ const plugin = {
|
|
|
4765
4786
|
features: billingData.features as BillingCache['features'] | undefined,
|
|
4766
4787
|
// Relay's authoritative chain_id → drives the chain override verbatim (#402).
|
|
4767
4788
|
chain_id: billingData.chain_id as number | undefined,
|
|
4789
|
+
// Relay's authoritative data_edge_address → drives the DataEdge override verbatim (#460).
|
|
4790
|
+
data_edge_address: billingData.data_edge_address as string | undefined,
|
|
4768
4791
|
checked_at: Date.now(),
|
|
4769
4792
|
};
|
|
4770
4793
|
writeBillingCache(cache);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@totalreclaw/totalreclaw",
|
|
3
|
-
"version": "3.3.12-rc.
|
|
3
|
+
"version": "3.3.12-rc.22",
|
|
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": [
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"scripts": {
|
|
69
69
|
"build": "rm -rf dist && tsc -p tsconfig.json --noCheck",
|
|
70
70
|
"verify-tarball": "node ../scripts/verify-tarball.mjs",
|
|
71
|
-
"test": "npx tsx batch-gate.test.ts && npx tsx manifest-shape.test.ts && npx tsx config-schema.test.ts && npx tsx config.test.ts && npx tsx relay-headers.test.ts && npx tsx scope-address-visible.test.ts && npx tsx llm-profile-reader.test.ts && npx tsx llm-client.test.ts && npx tsx llm-client-retry.test.ts && npx tsx llm-client-json-mode.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 pair-http.test.ts && npx tsx pair-http-route-registration.test.ts && npx tsx pair-http-init.test.ts && npx tsx qa-bug-report.test.ts && npx tsx nonce-serialization.test.ts && npx tsx initcode-lifecycle.test.ts && npx tsx phrase-safety-registry.test.ts && npx tsx test_issue_92_onnx_download_ux.test.ts && npx tsx onboard-pair-only.test.ts && npx tsx import-state.test.ts && npx tsx import-time-smoke.test.ts && npx tsx install-staging-cleanup.test.ts && npx tsx partial-install-detection.test.ts && npx tsx install-reload-idempotency.test.ts && npx tsx skill-register.test.ts && npx tsx json-stdout-cleanliness.test.ts && npx tsx url-binding.test.ts && npx tsx fs-helpers.test.ts && npx tsx pair-cli-default-mode.test.ts && npx tsx embedding-fallback-tag.test.ts && npx tsx staging-banner-gate.test.ts && npx tsx restart-auth.test.ts && npx tsx inbound-user-tracker.test.ts && npx tsx register-command-name.test.ts && npx tsx skill-md-native.test.ts &&npx tsx tr-cli-json-output.test.ts && npx tsx import-upgrade-cli.test.ts && npx tsx postinstall-validate.test.ts && npx tsx credential-provider.test.ts && npx tsx memory-runtime.test.ts && npx tsx tools.test.ts && npx tsx register-native.test.ts && npx tsx relay.test.ts && npx tsx vault-crypto.test.ts && npx tsx entry-env.test.ts && npx tsx trajectory-poller.test.ts && npx tsx billing-cache.test.ts",
|
|
71
|
+
"test": "npx tsx batch-gate.test.ts && npx tsx manifest-shape.test.ts && npx tsx config-schema.test.ts && npx tsx config.test.ts && npx tsx relay-headers.test.ts && npx tsx scope-address-visible.test.ts && npx tsx llm-profile-reader.test.ts && npx tsx llm-client.test.ts && npx tsx llm-client-retry.test.ts && npx tsx llm-client-json-mode.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 pair-http.test.ts && npx tsx pair-http-route-registration.test.ts && npx tsx pair-http-init.test.ts && npx tsx qa-bug-report.test.ts && npx tsx nonce-serialization.test.ts && npx tsx initcode-lifecycle.test.ts && npx tsx phrase-safety-registry.test.ts && npx tsx test_issue_92_onnx_download_ux.test.ts && npx tsx onboard-pair-only.test.ts && npx tsx import-state.test.ts && npx tsx import-time-smoke.test.ts && npx tsx install-staging-cleanup.test.ts && npx tsx partial-install-detection.test.ts && npx tsx install-reload-idempotency.test.ts && npx tsx skill-register.test.ts && npx tsx json-stdout-cleanliness.test.ts && npx tsx url-binding.test.ts && npx tsx fs-helpers.test.ts && npx tsx pair-cli-default-mode.test.ts && npx tsx embedding-fallback-tag.test.ts && npx tsx staging-banner-gate.test.ts && npx tsx restart-auth.test.ts && npx tsx inbound-user-tracker.test.ts && npx tsx register-command-name.test.ts && npx tsx skill-md-native.test.ts &&npx tsx tr-cli-json-output.test.ts && npx tsx import-upgrade-cli.test.ts && npx tsx cli-registercli-scope.test.ts && npx tsx postinstall-validate.test.ts && npx tsx credential-provider.test.ts && npx tsx memory-runtime.test.ts && npx tsx tools.test.ts && npx tsx register-native.test.ts && npx tsx relay.test.ts && npx tsx vault-crypto.test.ts && npx tsx entry-env.test.ts && npx tsx trajectory-poller.test.ts && npx tsx billing-cache.test.ts",
|
|
72
72
|
"smoke:dist": "npx tsx dist-esm-smoke.test.ts",
|
|
73
73
|
"check-scanner": "node ../scripts/check-scanner.mjs",
|
|
74
74
|
"check-version-drift": "node ../scripts/check-version-drift.mjs",
|
package/skill.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "totalreclaw",
|
|
3
|
-
"version": "3.3.12-rc.
|
|
3
|
+
"version": "3.3.12-rc.22",
|
|
4
4
|
"description": "End-to-end encrypted memory for AI agents — portable, yours forever. XChaCha20-Poly1305 E2EE: server never sees plaintext.",
|
|
5
5
|
"author": "TotalReclaw Team",
|
|
6
6
|
"license": "MIT",
|
package/subgraph-store.ts
CHANGED
|
@@ -21,7 +21,7 @@ function getWasm() {
|
|
|
21
21
|
if (!_wasm) _wasm = requireWasm('@totalreclaw/core');
|
|
22
22
|
return _wasm;
|
|
23
23
|
}
|
|
24
|
-
import { CONFIG } from './config.js';
|
|
24
|
+
import { CONFIG, getDataEdgeAddressOverride } from './config.js';
|
|
25
25
|
import { buildRelayHeaders } from './relay-headers.js';
|
|
26
26
|
import { rpcRequest, rpcWithRetry } from './relay.js';
|
|
27
27
|
import { signUserOp } from './vault-crypto.js';
|
|
@@ -844,7 +844,10 @@ export function isSubgraphMode(): boolean {
|
|
|
844
844
|
* - TOTALRECLAW_SELF_HOSTED -- set "true" to use self-hosted server (default: managed service)
|
|
845
845
|
*
|
|
846
846
|
* Chain ID is no longer configurable via env — it is auto-detected from the
|
|
847
|
-
* relay billing response (
|
|
847
|
+
* relay billing response (post-ops-1 both tiers are on Gnosis mainnet, chain
|
|
848
|
+
* 100). The DataEdge contract address is likewise consumed from the relay's
|
|
849
|
+
* authoritative `data_edge_address` (env override still wins, WASM default is
|
|
850
|
+
* the final fallback — see the `dataEdgeAddress` resolution below, #460).
|
|
848
851
|
*/
|
|
849
852
|
export function getSubgraphConfig(): SubgraphStoreConfig {
|
|
850
853
|
return {
|
|
@@ -853,7 +856,12 @@ export function getSubgraphConfig(): SubgraphStoreConfig {
|
|
|
853
856
|
mnemonic: CONFIG.recoveryPhrase,
|
|
854
857
|
cachePath: CONFIG.cachePath,
|
|
855
858
|
chainId: CONFIG.chainId,
|
|
856
|
-
|
|
859
|
+
// Resolution order (#460): explicit operator env override → relay billing
|
|
860
|
+
// `data_edge_address` (verbatim) → WASM-baked default. The relay routes
|
|
861
|
+
// each environment to its own DataEdge (staging is on-chain isolated), so
|
|
862
|
+
// consuming its value keeps writes + reads on the same contract; without
|
|
863
|
+
// the middle term staging writes mined on the prod default → empty recall.
|
|
864
|
+
dataEdgeAddress: CONFIG.dataEdgeAddress || getDataEdgeAddressOverride() || getWasm().getDataEdgeAddress(),
|
|
857
865
|
entryPointAddress: CONFIG.entryPointAddress || getWasm().getEntryPointAddress(),
|
|
858
866
|
rpcUrl: CONFIG.rpcUrl || undefined,
|
|
859
867
|
};
|
package/tr-cli.ts
CHANGED
|
@@ -68,7 +68,7 @@ const STATE_PATH = CONFIG.onboardingStatePath;
|
|
|
68
68
|
// Auto-synced by skill/scripts/sync-version.mjs from skill/plugin/package.json::version.
|
|
69
69
|
// Do not edit by hand — running tests will catch drift but the publish workflow
|
|
70
70
|
// rewrites this constant at the start of every npm/ClawHub publish.
|
|
71
|
-
const PLUGIN_VERSION = '3.3.12-rc.
|
|
71
|
+
const PLUGIN_VERSION = '3.3.12-rc.22';
|
|
72
72
|
|
|
73
73
|
function die(msg: string, code = 1): never {
|
|
74
74
|
process.stderr.write(`tr: ${msg}\n`);
|