@totalreclaw/totalreclaw 3.3.1-rc.2 → 3.3.1-rc.20
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 +283 -0
- package/SKILL.md +50 -83
- package/config.ts +57 -0
- package/dist/api-client.js +220 -0
- package/dist/billing-cache.js +100 -0
- package/dist/claims-helper.js +606 -0
- package/dist/config.js +223 -0
- package/dist/consolidation.js +258 -0
- package/dist/contradiction-sync.js +1034 -0
- package/dist/crypto.js +130 -0
- package/dist/digest-sync.js +361 -0
- package/dist/download-ux.js +63 -0
- package/dist/embedding.js +86 -0
- package/dist/extractor.js +1225 -0
- package/dist/first-run.js +103 -0
- package/dist/fs-helpers.js +481 -0
- package/dist/gateway-url.js +197 -0
- package/dist/generate-mnemonic.js +13 -0
- package/dist/hot-cache-wrapper.js +101 -0
- package/dist/import-adapters/base-adapter.js +64 -0
- package/dist/import-adapters/chatgpt-adapter.js +238 -0
- package/dist/import-adapters/claude-adapter.js +114 -0
- package/dist/import-adapters/gemini-adapter.js +201 -0
- package/dist/import-adapters/index.js +26 -0
- package/dist/import-adapters/mcp-memory-adapter.js +219 -0
- package/dist/import-adapters/mem0-adapter.js +158 -0
- package/dist/import-adapters/types.js +1 -0
- package/dist/index.js +5233 -0
- package/dist/llm-client.js +686 -0
- package/dist/llm-profile-reader.js +346 -0
- package/dist/lsh.js +57 -0
- package/dist/onboarding-cli.js +750 -0
- package/dist/pair-cli.js +344 -0
- package/dist/pair-crypto.js +359 -0
- package/dist/pair-http.js +404 -0
- package/dist/pair-page.js +826 -0
- package/dist/pair-qr.js +107 -0
- package/dist/pair-remote-client.js +410 -0
- package/dist/pair-session-store.js +566 -0
- package/dist/pin.js +542 -0
- package/dist/qa-bug-report.js +301 -0
- package/dist/reranker.js +442 -0
- package/dist/retype-setscope.js +348 -0
- package/dist/semantic-dedup.js +75 -0
- package/dist/subgraph-search.js +288 -0
- package/dist/subgraph-store.js +689 -0
- package/dist/tool-gating.js +58 -0
- package/download-ux.ts +91 -0
- package/embedding.ts +32 -9
- package/fs-helpers.ts +32 -0
- package/gateway-url.ts +57 -9
- package/index.ts +436 -334
- package/llm-client.ts +211 -23
- package/onboarding-cli.ts +114 -1
- package/package.json +18 -5
- package/pair-cli.ts +76 -8
- package/pair-crypto.ts +34 -24
- package/pair-page.ts +28 -17
- package/pair-qr.ts +152 -0
- package/pair-remote-client.ts +540 -0
- package/qa-bug-report.ts +381 -0
- package/reranker.ts +73 -0
- package/retype-setscope.ts +12 -0
- package/subgraph-store.ts +94 -6
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,289 @@ 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.16] — 2026-04-24
|
|
8
|
+
|
|
9
|
+
Fixes #92 — slow-host install times out during ONNX-runtime / embedding-model
|
|
10
|
+
download. ONNX stays mandatory (no opt-in flag); first-call download is now
|
|
11
|
+
wrapped with timeout, progress, and retry UX so slow connections succeed
|
|
12
|
+
instead of silently hanging until OpenClaw SIGTERMs.
|
|
13
|
+
|
|
14
|
+
### Embedding-model download UX
|
|
15
|
+
|
|
16
|
+
- New `download-ux.ts` module — pure stdlib, no third-party imports — exposes
|
|
17
|
+
`downloadWithUX(label, fn, opts)`. Wraps a download promise with:
|
|
18
|
+
- **Per-attempt timeout**, default 600s (covers ~290 KB/s for the 344 MB
|
|
19
|
+
Harrier model). Configurable via env `TOTALRECLAW_ONNX_INSTALL_TIMEOUT`
|
|
20
|
+
(in seconds). Per-attempt timeout grows 1x/2x/4x across retries.
|
|
21
|
+
- **60s keep-alive log** during long downloads so users on slow networks
|
|
22
|
+
see "still downloading… (Ns elapsed)" rather than a frozen prompt.
|
|
23
|
+
- **3-attempt exponential-backoff retry** (5s/10s backoff between attempts)
|
|
24
|
+
to absorb transient network blips.
|
|
25
|
+
- **Loud actionable error** on exhaustion: names the env var to extend the
|
|
26
|
+
timeout and the exact `openclaw plugins install totalreclaw` command to
|
|
27
|
+
rerun.
|
|
28
|
+
- `embedding.ts` now wraps `AutoTokenizer.from_pretrained`,
|
|
29
|
+
`AutoModel.from_pretrained`, and the `pipeline()` call with
|
|
30
|
+
`downloadWithUX`. Prints a user-visible "Downloading embedding model
|
|
31
|
+
(~344MB) — this may take a few minutes on slower connections. Please wait."
|
|
32
|
+
message before the first download starts.
|
|
33
|
+
- ONNX remains a mandatory hard `dependency` (no `[embedding]`-style opt-in
|
|
34
|
+
extra). Recall accuracy is unchanged.
|
|
35
|
+
- Regression: `test_issue_92_onnx_download_ux.test.ts` exercises happy path,
|
|
36
|
+
transient failure → retry, full exhaustion, per-attempt timeout, and
|
|
37
|
+
keep-alive cadence. Wired into the plugin `npm test` chain.
|
|
38
|
+
|
|
39
|
+
## [3.3.1-rc.14] — 2026-04-24
|
|
40
|
+
|
|
41
|
+
Coordinated version bump with Python `2.3.1rc14`. Two narrow bug fixes
|
|
42
|
+
found during rc.13 user QA on 2026-04-24:
|
|
43
|
+
|
|
44
|
+
### RC-gated QA bug tool — target-repo hardening
|
|
45
|
+
|
|
46
|
+
`totalreclaw_report_qa_bug` now refuses to file to any repo that isn't
|
|
47
|
+
internal. rc.13 user QA surfaced agent-filed bug reports leaking to the
|
|
48
|
+
public `p-diogo/totalreclaw` tracker despite the tool's default target
|
|
49
|
+
being `p-diogo/totalreclaw-internal`.
|
|
50
|
+
|
|
51
|
+
- New env var: `TOTALRECLAW_QA_REPO` lets operators point the tool at a
|
|
52
|
+
private fork. The default stays `p-diogo/totalreclaw-internal`.
|
|
53
|
+
- New `resolveQaRepo(...)` guard: rejects any slug that is on the
|
|
54
|
+
public-repo denylist (includes `p-diogo/totalreclaw`,
|
|
55
|
+
`...-website`, `...-relay`, `...-plugin`, `...-hermes`) OR does not
|
|
56
|
+
end in `-internal`. The check runs before the HTTP POST is
|
|
57
|
+
constructed, so rejection never leaves the client.
|
|
58
|
+
- `CONFIG.qaRepoOverride` surfaces the env var through `config.ts`
|
|
59
|
+
(keeps scanner-sensitive `process.env` reads centralized).
|
|
60
|
+
- Regression test in `qa-bug-report.test.ts` mocks the public slug
|
|
61
|
+
and asserts `fetch` is NEVER called.
|
|
62
|
+
|
|
63
|
+
Labels on filing unchanged — still emits `qa-bug`, `pending-triage`,
|
|
64
|
+
`severity:<...>`, `component:<...>`, `rc:<...>`.
|
|
65
|
+
|
|
66
|
+
### Relay pair page — PIN paste button UX
|
|
67
|
+
|
|
68
|
+
The paste button on the step-1 PIN screen was silently failing under
|
|
69
|
+
certain browser states. rc.14 rewrites the handler with a proper
|
|
70
|
+
error taxonomy:
|
|
71
|
+
|
|
72
|
+
- Capability probe up front — `navigator.clipboard.readText` missing →
|
|
73
|
+
clear "Paste unavailable on this browser" toast.
|
|
74
|
+
- `NotAllowedError` → "Clipboard access denied — type the 6 digits
|
|
75
|
+
manually" (covers iOS Safari permission denial).
|
|
76
|
+
- Empty clipboard → "Clipboard is empty — copy the PIN from your chat
|
|
77
|
+
first".
|
|
78
|
+
- Non-digit content → "Clipboard has no digits — copy the 6-digit PIN
|
|
79
|
+
first".
|
|
80
|
+
- Every failure path focuses the first PIN cell so the user can fall
|
|
81
|
+
through to manual typing without another click.
|
|
82
|
+
- Errors log to `console.warn` with name + message so future failures
|
|
83
|
+
are diagnosable from browser devtools.
|
|
84
|
+
|
|
85
|
+
The mockup at `docs/mockups/rc13-pair-wizard/wizard.js` gets the same
|
|
86
|
+
rewrite for parity — the relay's `scripts/sync-pair-preview.mjs`
|
|
87
|
+
regenerates `/pair-preview/` from this source.
|
|
88
|
+
|
|
89
|
+
Fix also applies to the "Paste all 12 words" import-grid button on the
|
|
90
|
+
relay production page (same taxonomy, same focus-fallback).
|
|
91
|
+
|
|
92
|
+
## [3.3.1-rc.13] — 2026-04-24
|
|
93
|
+
|
|
94
|
+
Coordinated version bump with Python `2.3.1rc13`. No substantive
|
|
95
|
+
changes to the plugin's own TypeScript — the rc.13 fix lands on the
|
|
96
|
+
Hermes-side (`python/src/totalreclaw/hermes/pair_tool.py`) where the
|
|
97
|
+
asyncio lifecycle regression lived. We keep plugin + Python RC
|
|
98
|
+
numbers in lockstep so the release-pipeline tracker and
|
|
99
|
+
`qa-totalreclaw` skill carry both artifacts through QA as one
|
|
100
|
+
bundle.
|
|
101
|
+
|
|
102
|
+
See the corresponding entry in `python/CHANGELOG.md` for the full
|
|
103
|
+
design: the relay-pair WebSocket is now owned by a dedicated worker
|
|
104
|
+
thread (with its own event loop) so it survives the Hermes
|
|
105
|
+
tool-invocation loop teardown that destroyed the rc.10–rc.12 waiter
|
|
106
|
+
mid-recv and caused every pair attempt to 502.
|
|
107
|
+
|
|
108
|
+
The relay-served production pair page is also replaced with the
|
|
109
|
+
rc.13 wizard UX — a typeform-style 3-step flow (PIN → phrase → done)
|
|
110
|
+
mirroring the `docs/mockups/rc13-pair-wizard/` design. This lands in
|
|
111
|
+
the `totalreclaw-relay` repo PR, not here, but surfaces to every
|
|
112
|
+
OpenClaw user via the default relay pair flow.
|
|
113
|
+
|
|
114
|
+
### Plugin local-mode pair page
|
|
115
|
+
|
|
116
|
+
`skill/plugin/pair-page.ts` (the local-mode fallback served when a
|
|
117
|
+
user sets `TOTALRECLAW_PAIR_MODE=local`) retains its rc.10–rc.12 UX
|
|
118
|
+
shape. The wizard UX port for this file is deferred to rc.14 pending
|
|
119
|
+
a design decision on whether to share a single CSS+JS asset across
|
|
120
|
+
all three pair pages (relay / Python local / plugin local) or keep
|
|
121
|
+
them independently inlined. Local-mode is rarely exercised — the
|
|
122
|
+
plugin defaults to the relay flow via the Hermes Python sidecar and
|
|
123
|
+
only falls back here for air-gapped setups.
|
|
124
|
+
|
|
125
|
+
## [3.3.1-rc.12] — 2026-04-23
|
|
126
|
+
|
|
127
|
+
**Ship-stopper fix for rc.11.** The relay-served pair page's submit
|
|
128
|
+
button threw `NotSupportedError: Failed to execute 'importKey' on
|
|
129
|
+
'SubtleCrypto': Algorithm: Unrecognized name` when the user clicked
|
|
130
|
+
"Seal key and finish". Root cause: `ChaCha20-Poly1305` is NOT
|
|
131
|
+
implemented in the Web Crypto API of Chrome / Safari / Edge — the
|
|
132
|
+
spec exposes `AES-GCM` as the only AEAD. rc.10/rc.11 never worked
|
|
133
|
+
end-to-end for any user; every pair attempt failed silently and the
|
|
134
|
+
token expired without logging a failure — GH issue #79.
|
|
135
|
+
|
|
136
|
+
rc.12 swaps the cipher suite from ChaCha20-Poly1305 to AES-256-GCM on
|
|
137
|
+
both sides (browser + gateway). Wire shape unchanged — still 12-byte
|
|
138
|
+
nonce, 16-byte tag, sid-bound AAD, base64url encoding. HKDF info bumped
|
|
139
|
+
from `totalreclaw-pair-v1` to `totalreclaw-pair-v2` so rc.11 ciphertexts
|
|
140
|
+
cannot collide with rc.12 keys (fail-closed on any version skew).
|
|
141
|
+
|
|
142
|
+
### Changed
|
|
143
|
+
- `skill/plugin/pair-crypto.ts`: `aeadDecrypt` / `aeadEncryptWithSessionKey`
|
|
144
|
+
switched from `chacha20-poly1305` to `aes-256-gcm`. `HKDF_INFO` bumped
|
|
145
|
+
to `totalreclaw-pair-v2`.
|
|
146
|
+
- `skill/plugin/pair-page.ts` (local-mode pair page): WebCrypto
|
|
147
|
+
`ChaCha20-Poly1305` calls swapped to `AES-GCM`. Capability probe
|
|
148
|
+
function renamed `chaChaSupported` → `aesGcmSupported`.
|
|
149
|
+
|
|
150
|
+
### Observability
|
|
151
|
+
- The relay's `pair-html.ts` (user-facing page) now reports phase-labelled
|
|
152
|
+
error messages so a network / encrypt / submit failure no longer masks
|
|
153
|
+
as a silent "stuck on acknowledge screen". Relay PR (fix/pair-aes-gcm-rc12)
|
|
154
|
+
is the canonical fix for the issue reported in #79.
|
|
155
|
+
|
|
156
|
+
## [3.3.1-rc.11] — 2026-04-23
|
|
157
|
+
|
|
158
|
+
OpenClaw-side universal pair reachability — the plugin's `totalreclaw_pair` tool now routes through the relay WebSocket by default, mirroring the Python `2.3.1rc10` pivot on the Hermes side. The URL returned to the user is `https://api-staging.totalreclaw.xyz/pair/p/<token>#pk=<gateway_pubkey>` instead of the previous `http://<gateway-host>:<port>/plugin/totalreclaw/pair/finish?sid=<sid>#pk=…`. Managed hosts, Docker-in-cloud setups, phone-scan-QR flows, and split-network operators can now complete pairing without the browser needing loopback or LAN access to the gateway.
|
|
159
|
+
|
|
160
|
+
Paired with Hermes Python `2.3.1rc11` — both clients now reach for the relay by default, and `TOTALRECLAW_PAIR_MODE=local` on either side restores the rc.4–rc.10 loopback flow for air-gapped / self-hosted deployments.
|
|
161
|
+
|
|
162
|
+
### Added
|
|
163
|
+
|
|
164
|
+
- **`skill/plugin/pair-remote-client.ts`** — new. TypeScript mirror of `python/src/totalreclaw/pair/remote_client.py` (rc.10 Hermes):
|
|
165
|
+
- `openRemotePairSession({ relayBaseUrl?, pin?, clientId?, mode? })` — generates an ephemeral x25519 keypair via the existing `pair-crypto.ts` module, opens a WebSocket to `/pair/session/open`, sends `{type:"open", gateway_pubkey, pin, client_id, mode}`, and returns a `RemotePairSession` handle containing the user-facing URL (with `#pk=` fragment), PIN, token, expiry, and the live WebSocket.
|
|
166
|
+
- `awaitPhraseUpload(session, { completePairing, phraseValidator?, timeoutMs? })` — blocks on the kept-open WebSocket until the relay pushes `{type:"forward", client_pubkey, nonce, ciphertext}`. Decrypts locally via `decryptPairingPayload` using the gateway's private key (same ECDH + HKDF + ChaCha20-Poly1305 primitives as rc.10's loopback flow — byte-compatible with Python's `pair.crypto`). Runs the caller-supplied `completePairing` handler and sends `{type:"ack"}` back on success or `{type:"nack", error}` on validator / decrypt / completion failure.
|
|
167
|
+
- `pairViaRelay(...)` — one-shot convenience wrapper for tests and simple callers.
|
|
168
|
+
- **`ws` runtime dep** (`^8.18.3`) + **`@types/ws`** — pure-JS WebSocket client. Transitive already via `@totalreclaw/core`; rc.11 promotes it to a direct dep so the plugin's own import graph is explicit.
|
|
169
|
+
- **`TOTALRECLAW_PAIR_MODE`** env (plugin side) — mirrors the Python env. Unset or any non-`local` value routes through the relay; `local` preserves the rc.4–rc.10 loopback HTTP server served by `pair-http.ts` (`/plugin/totalreclaw/pair/{finish,start,respond,status}`).
|
|
170
|
+
- **`TOTALRECLAW_PAIR_RELAY_URL`** env (plugin side) — self-hosters can point at their own relay. Defaults to `wss://api-staging.totalreclaw.xyz`.
|
|
171
|
+
- **`skill/plugin/pair-remote-client.test.ts`** — 20 assertions across 5 scenarios: happy-path round-trip, invalid-phrase nack, relay open error, decrypt failure, https-to-wss scheme conversion. Runs against a local `ws` server stub — no network dependency.
|
|
172
|
+
|
|
173
|
+
### Changed
|
|
174
|
+
|
|
175
|
+
- **`totalreclaw_pair` tool** now branches on `CONFIG.pairMode`. In relay mode it returns the URL + PIN immediately and schedules a background task that blocks on the WebSocket until the browser completes (or the TTL lapses). Credentials-write happens in that background task via the same `loadCredentialsJson` / `writeCredentialsJson` / `setRecoveryPhraseOverride` / `writeOnboardingState` side-effect chain that the loopback `pair-http.respond` handler uses — so the onboarding-state flip remains identical. Tool payload shape unchanged (`{url, pin, expires_at_ms, qr_ascii, qr_png_b64, qr_unicode, mode}`) except for a new `transport: 'relay' | 'local'` field that tooling (QA harness, telemetry) can use to confirm which path served a given URL.
|
|
176
|
+
|
|
177
|
+
### Phrase-safety invariants (preserved)
|
|
178
|
+
|
|
179
|
+
- Relay is blind: the gateway's ephemeral x25519 private key never leaves the plugin host. The relay forwards opaque ciphertext; it cannot derive the symmetric key.
|
|
180
|
+
- PIN is out-of-band: the user reads the PIN from agent chat and types it into the browser. The relay stores the PIN in memory only; logs carry no PIN, no ciphertext, no pubkey, no phrase.
|
|
181
|
+
- Session state is in-memory on the relay with a 5-minute TTL. Redis deferred to Phase 2 per the design blueprint.
|
|
182
|
+
- Backwards-compat: `TOTALRECLAW_PAIR_MODE=local` preserves every bit of the rc.4–rc.10 flow — same loopback HTTP server, same session store, same browser page, same decrypt handler.
|
|
183
|
+
|
|
184
|
+
### Mechanism / byte-compat
|
|
185
|
+
|
|
186
|
+
The crypto is a literal TypeScript binding against the same `pair-crypto.ts` module `pair-http.ts` already imports. No new cipher suite, no new wire format — only the transport (WebSocket to relay + relay-served HTML page) differs from the loopback path. A ciphertext produced by the relay-served `pair-html.ts` page decrypts under the same gateway private key using the same `decryptPairingPayload(...)` call path. This is deliberate: `pair-crypto.ts` is the byte-compat anchor shared with Python's `pair.crypto`, and rc.11 extends that anchor to the relay wire.
|
|
187
|
+
|
|
188
|
+
## [3.3.1-rc.10] — 2026-04-23
|
|
189
|
+
|
|
190
|
+
Coordinated version bump with Hermes Python `2.3.1rc10`. rc.10 ships the relay-brokered pair flow — see `python/CHANGELOG.md` (the `2.3.1rc10` entry) for the full design. The `totalreclaw_pair` pair URL on the OpenClaw plugin side still uses the gateway-loopback HTTP server (the OpenClaw plugin runs in-process alongside a browser on the same host for most deployments, so the loopback URL actually reaches the user). The relay-brokered path is currently Hermes-side only — the OpenClaw plugin can pick it up in a later RC if the same universal-reachability problem starts biting OpenClaw users.
|
|
191
|
+
|
|
192
|
+
Bundled into rc.10: the previously-parked rc.5 QR display layer from PR #76 (`pair-qr.ts` + `pair-qr.test.ts`, tool-payload `qr_png_b64` + `qr_unicode` fields, `totalreclaw_setup` / `totalreclaw_onboarding_start` stub removal). All rebased onto main via the chore/rc.10-qr-rebase-pr76 branch.
|
|
193
|
+
|
|
194
|
+
### Added (rebased from PR #76)
|
|
195
|
+
|
|
196
|
+
- **`skill/plugin/pair-qr.ts`** — new. QR encoder module wrapping `qrcode` (PNG) + `qrcode-terminal` (Unicode block). Same contract as the Python side (`totalreclaw.pair.qr`).
|
|
197
|
+
- **`totalreclaw_pair` tool payload** — the `details` block now carries `qr_png_b64` (base64 PNG for image transports) and `qr_unicode` (terminal block-char string) alongside the existing `qr_ascii`. URL + PIN unchanged.
|
|
198
|
+
- **SKILL.md "Rendering the QR on your transport" section** — per-transport agent rendering guidance (Telegram attachment, terminal inline, web chat `<img>` embed).
|
|
199
|
+
- **`qrcode` + `@types/qrcode`** runtime deps.
|
|
200
|
+
|
|
201
|
+
### Removed (rc.5 phrase-safety carve-out closure, rebased)
|
|
202
|
+
|
|
203
|
+
- **`totalreclaw_setup` + `totalreclaw_onboarding_start`** agent tools — both were neutered pointer stubs in rc.4; rc.5 auto-QA flagged them as future-regression surface and their mere presence signalled to agents that "phrase handling happens here". Deleted outright in rc.5, preserved through rc.10. `skill/plugin/phrase-safety-registry.test.ts` now asserts neither name is registered.
|
|
204
|
+
|
|
205
|
+
Version bump reason: rc cadence keeps Python + plugin aligned so the release-pipeline tracker carries them through QA as one artifact set.
|
|
206
|
+
|
|
207
|
+
## [3.3.1-rc.9] — 2026-04-23
|
|
208
|
+
|
|
209
|
+
Coordinated version bump with Hermes Python `2.3.1rc9`. Plugin code itself is unchanged from `3.3.1-rc.6` (the first-run banner fix lives entirely on the Python side — `totalreclaw.onboarding.maybe_emit_welcome`). The rc.9 bundle ships the Hermes-side banner suppression and keeps plugin + Python versions aligned so the release-pipeline tracker can carry them through QA as one artifact set.
|
|
210
|
+
|
|
211
|
+
### Why a plugin bump when only Python changed
|
|
212
|
+
|
|
213
|
+
Our RC cadence publishes both registries from the same bundle. Out-of-sync version tags cause downstream confusion (the `qa-totalreclaw` skill and the release-pipeline tracker both key on a single RC-number per wave). Skipping the plugin bump would leave rc.9 documented on the Python side only; a later plugin bug would then have to skip to rc.10 to catch up. Much simpler to bump both in lockstep.
|
|
214
|
+
|
|
215
|
+
See `python/CHANGELOG.md` (the `2.3.1rc9` entry) for the underlying fix: suppress the first-run welcome banner emitted by `totalreclaw.onboarding.maybe_emit_welcome`. Two problems surfaced during the rc.8 Hermes auto-QA run:
|
|
216
|
+
|
|
217
|
+
1. **Chat-breaker.** The banner dominated `hermes chat -q` stdout when credentials were absent, breaking the QA harness's `session_id` parsing on every fresh install.
|
|
218
|
+
2. **Phrase-safety violation.** The banner told users to `Run: totalreclaw setup` — a CLI that emits the recovery phrase to stdout. In an agent-driven context, stdout is echoed back into LLM context, so the phrase would cross the LLM boundary in violation of `project_phrase_safety_rule.md`.
|
|
219
|
+
|
|
220
|
+
Agent-driven setup now routes through the `totalreclaw_pair` tool (browser-side crypto, phrase-safe) per SKILL.md. User-in-terminal setup still runs through `totalreclaw setup` / `openclaw totalreclaw onboard` OUTSIDE any agent context.
|
|
221
|
+
|
|
222
|
+
### Skipped
|
|
223
|
+
|
|
224
|
+
- **`3.3.1-rc.7`** and **`3.3.1-rc.8`** — registry-only bumps from 2026-04-22 workflow dispatches; the git repo on `main` carried rc.6 code unchanged through both publishes.
|
|
225
|
+
|
|
226
|
+
## [3.3.1-rc.6] — 2026-04-22
|
|
227
|
+
|
|
228
|
+
Coordinated version bump with Hermes Python `2.3.1rc6`. Plugin code itself is unchanged from `3.3.1-rc.4` (the OpenClaw plugin's `register()` path already wired every tool advertised in `skill.yaml`). The rc.6 bundle ships the Hermes-side tool-registration fix and keeps plugin + Python versions aligned so the release-pipeline tracker can carry them through QA as one artifact set.
|
|
229
|
+
|
|
230
|
+
### Why a plugin bump when only Python changed
|
|
231
|
+
|
|
232
|
+
Our RC cadence publishes both registries from the same bundle. Out-of-sync version tags cause downstream confusion (the `qa-totalreclaw` skill and the release-pipeline tracker both key on a single RC-number per wave). Skipping the plugin bump would leave rc.6 documented on the Python side only; a later plugin bug would then have to skip to rc.7 to catch up. Much simpler to bump both in lockstep.
|
|
233
|
+
|
|
234
|
+
### Skipped
|
|
235
|
+
|
|
236
|
+
- **`3.3.1-rc.5`** — PR #76 (branch `fix/plugin-3.3.1-rc.5-qr-display`) remained unmerged when the rc.4 Hermes regression was escalated. rc.5's QR-display work rebases onto rc.6 as a follow-up.
|
|
237
|
+
|
|
238
|
+
## [3.3.1-rc.4] — 2026-04-22
|
|
239
|
+
|
|
240
|
+
Phrase-safety hardening: `totalreclaw_onboard` agent tool removed. Paired with Hermes Python `2.3.1rc4` (which ports the QR-pair flow to Python so Hermes users gain a phrase-safe agent setup path too).
|
|
241
|
+
|
|
242
|
+
### Removed (phrase-safety enforcement — BREAKING for agent tool callers)
|
|
243
|
+
|
|
244
|
+
- **`totalreclaw_onboard` agent tool — REMOVED.** rc.3 shipped a `totalreclaw_onboard` tool that generated a fresh BIP-39 mnemonic in-process, wrote it to `credentials.json`, and returned `{scope_address, credentials_path}`. `emitPhrase: false` kept the mnemonic out of the tool's return payload, but NOTHING ARCHITECTURALLY PREVENTED leakage — a future patch could regress the flag, a different code path could echo the mnemonic in a log/error, or the mere existence of the tool signalled to agents that phrase generation inside chat is fine (it isn't). Per `project_phrase_safety_rule.md`: "recovery phrase MUST NEVER cross the LLM context in ANY form." rc.4 removes the registration. The underlying `runNonInteractiveOnboard` code path stays reachable via the CLI `openclaw totalreclaw onboard` — that path runs in the user's own terminal, OUTSIDE any agent shell, so phrase stdout never feeds back into LLM context.
|
|
245
|
+
|
|
246
|
+
### Changed
|
|
247
|
+
|
|
248
|
+
- **`SKILL.md` — setup section rewritten.** `totalreclaw_pair` is now the canonical setup surface for all users (local or remote). The CLI wizard (`openclaw totalreclaw onboard`) is explicitly documented as user-terminal-only — agents MUST NOT invoke it via their shell tool. Tool surface table updated: `totalreclaw_onboard` removed, `totalreclaw_pair` promoted to canonical. `totalreclaw_onboarding_start` remains as a pointer-only tool for users who explicitly prefer local-terminal setup.
|
|
249
|
+
- **`index.ts` — `totalreclaw_pair` tool description updated.** Removed backref to `totalreclaw_onboard`; now instructs agents to always prefer pair, with `totalreclaw_onboarding_start` as the fallback pointer for local-terminal-only users.
|
|
250
|
+
- **`docs/guides/openclaw-setup.md` — QR pairing is now documented as the default setup flow.** CLI wizard moved to a user-terminal-only subsection with a prominent "do NOT run this through an agent shell" warning.
|
|
251
|
+
|
|
252
|
+
### Tests
|
|
253
|
+
|
|
254
|
+
- **`phrase-safety-registry.test.ts`** — new. Text-scans `index.ts` for `api.registerTool({ name: '...' })` literals and asserts: (a) `totalreclaw_onboard` is NOT in the list; (b) `totalreclaw_pair` IS in the list; (c) no name contains phrase-adjacent tokens (`onboard_generate`, `generate_phrase`, `generate_mnemonic`, `restore_phrase`, `restore_mnemonic`, `mnemonic`). Runs as part of `npm test`.
|
|
255
|
+
|
|
256
|
+
## [3.3.1-rc.3] — 2026-04-22
|
|
257
|
+
|
|
258
|
+
Patch RC bundling two stability fixes, one new RC-gated tool, two SKILL.md addendums, and a configurable LLM retry budget. All prior rc.1 + rc.2 fixes are preserved.
|
|
259
|
+
|
|
260
|
+
### Changed
|
|
261
|
+
|
|
262
|
+
- **`llm-client.ts` — configurable `ZAI_BASE_URL` + auto-fallback on "Insufficient balance" 429.** rc.2 QA surfaced that GLM Coding Plan keys hitting the STANDARD zai endpoint (and PAYG keys hitting CODING) return HTTP 429 with body `"Insufficient balance or no resource package. Please recharge."` — misleading because the key itself is valid. rc.3: (a) accepts `ZAI_BASE_URL` env override via `config.ts` / `getZaiBaseUrl()`; (b) auto-detects the error signature and flips CODING ↔ STANDARD once per call (logged at INFO). SKILL.md now documents "GLM Coding Plan → leave unset; PAYG → set `ZAI_BASE_URL=https://api.z.ai/api/paas/v4`."
|
|
263
|
+
- **`llm-client.ts` — retry budget 7s → ~62s (configurable).** rc.1/rc.2 QA: 5–9 of 10 extraction windows returned 0 facts against multi-minute upstream 429 storms. The 3-attempt 1s/2s/4s backoff couldn't outlast a 9-minute outage. rc.3: 5 attempts, 2s/4s/8s/16s/32s backoff, total ~62s. Configurable via `TOTALRECLAW_LLM_RETRY_BUDGET_MS` env (default 60_000). First retry logs at INFO, rest at DEBUG (debounced — no spam during long outages). On exhaustion throws `LLMUpstreamOutageError` (structured, `attempts` + `lastStatus`) so extraction callers can recognise vs bail silently. Non-retryable errors (401/403/404/parse) still propagate as plain `Error`.
|
|
264
|
+
- **`subgraph-store.ts` — per-account submission mutex.** rc.2 logged 16 AA25 `invalid account nonce` events from concurrent `submitFactBatchOnChain` / `submitFactOnChain` calls racing at the `eth_call getNonce(sender, 0)` step. rc.3 wraps both submission entry points in a per-`sender` `Map<scopeAddress, Promise>` chain so only one UserOp is in flight per Smart Account at a time. The existing AA25-retry-with-fresh-nonce path is unchanged and still catches relay-side zombie UserOps.
|
|
265
|
+
|
|
266
|
+
### Added
|
|
267
|
+
|
|
268
|
+
- **`totalreclaw_report_qa_bug`** (RC-gated tool) — lets agents file structured QA-bug issues to `p-diogo/totalreclaw-internal` without the maintainer opening a fresh issue per RC finding. Only registered when the plugin version matches the `-rc.` token (via `readPluginVersion` in `fs-helpers.ts` + `isRcBuild` in the new `qa-bug-report.ts`). Handler POSTs to `https://api.github.com/repos/.../issues` with `Authorization: Bearer <token>` where `token = CONFIG.qaGithubToken` (reads `TOTALRECLAW_QA_GITHUB_TOKEN` or `GITHUB_TOKEN`). Secrets (BIP-39 phrases, `sk-*`, `AIzaSy*`, Telegram bot tokens, bearer tokens, 64+ char hex blobs, 0x-private-keys, `token=`/`secret=` qualifiers) are redacted fail-close in `redactSecrets()` before POST. Stable builds never expose this tool. See SKILL.md "Filing QA bugs (RC builds only)" for trigger rules — always ask user before filing, never the same bug twice.
|
|
269
|
+
- **`skill/plugin/qa-bug-report.ts`** — new pure-logic + HTTP module. Exports `isRcBuild`, `redactSecrets`, `validateQaBugArgs`, `buildIssueBody`, `postQaBugIssue`. Unit-tested in `qa-bug-report.test.ts`.
|
|
270
|
+
- **`skill/plugin/nonce-serialization.test.ts`** — exercises the per-`sender` mutex primitive: same-sender serializes, different-sender runs in parallel, case-insensitive keying, first-call failure releases the lock for the next.
|
|
271
|
+
- **`fs-helpers.ts` — `readPluginVersion(packageJsonDir)`** — scanner-safe helper used by the RC gate. Resolves via `path.dirname(fileURLToPath(import.meta.url))` in `index.ts` and returns the `version` field from `package.json` next to the module.
|
|
272
|
+
|
|
273
|
+
### SKILL.md
|
|
274
|
+
|
|
275
|
+
- **First-person recall rule.** rc.2 debug found agents skipped `totalreclaw_recall` in 5/5 attempts on "Where do I live?". SKILL.md now hard-rules it: any first-person factual query ("where do I live/work", "what do I prefer", "my [noun]", etc.) MUST call recall first. If recall returns 0, say "I don't have anything about that yet" rather than invent.
|
|
276
|
+
- **QA bug triggers.** New "Filing QA bugs (RC builds only)" section with the four triggers (repeated tool failure, user friction signals, setup errors, docs-vs-reality mismatch). Offer to file, never auto-file, never same bug twice.
|
|
277
|
+
- **zai endpoint + retry budget** documented in a new "zai provider configuration" section.
|
|
278
|
+
|
|
279
|
+
### Tests
|
|
280
|
+
|
|
281
|
+
- `llm-client-retry.test.ts` extended from 29 → 59 assertions. Covers: balance-error detection, CODING↔STANDARD fallback URL helper, `ZAI_BASE_URL` env override, full fallback happy/sad paths, `LLMUpstreamOutageError` surfacing, budget short-circuit.
|
|
282
|
+
- `qa-bug-report.test.ts` — 57 assertions covering isRcBuild, redactSecrets (BIP-39 / sk- / AIza / Telegram / Bearer / hex / private-key / preservation of UUIDs+SHAs+addresses), validateQaBugArgs, buildIssueBody, postQaBugIssue success + all failure paths.
|
|
283
|
+
- `nonce-serialization.test.ts` — 9 assertions.
|
|
284
|
+
- All existing tests (`llm-client.test.ts`, `manifest-shape.test.ts`, etc.) unchanged and green.
|
|
285
|
+
|
|
286
|
+
### Scanner
|
|
287
|
+
|
|
288
|
+
- `check-scanner.mjs` still passes (0 flags). The `TOTALRECLAW_QA_GITHUB_TOKEN` + `ZAI_BASE_URL` + `TOTALRECLAW_LLM_RETRY_BUDGET_MS` env reads live in `config.ts` (the env-harvesting-free house). `llm-client.ts`, `index.ts`, and `qa-bug-report.ts` all stay off `process.env`.
|
|
289
|
+
|
|
7
290
|
## [3.3.1-rc.2] — 2026-04-22
|
|
8
291
|
|
|
9
292
|
Follow-up RC for the 3.3.1-rc.1 QA NO-GO
|
package/SKILL.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: totalreclaw
|
|
3
|
-
description: "
|
|
4
|
-
version: 3.3.1-rc.
|
|
3
|
+
description: "Install + set up TotalReclaw encrypted memory for OpenClaw, then use totalreclaw_remember / totalreclaw_recall. Trigger on 'install TotalReclaw', 'set up TotalReclaw', 'restore my recovery phrase', or any remember / recall request."
|
|
4
|
+
version: 3.3.1-rc.11
|
|
5
5
|
author: TotalReclaw Team
|
|
6
6
|
license: MIT
|
|
7
7
|
homepage: https://totalreclaw.xyz
|
|
@@ -22,95 +22,62 @@ metadata:
|
|
|
22
22
|
- persistent-context
|
|
23
23
|
---
|
|
24
24
|
|
|
25
|
-
# TotalReclaw —
|
|
25
|
+
# TotalReclaw — OpenClaw
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
> The canonical install flow lives at <https://github.com/p-diogo/totalreclaw/blob/main/docs/guides/openclaw-setup.md>. If a user pastes that URL in chat, fetch it and follow its agent-instructions section. This SKILL.md mirrors the same steps so you can act even if the URL is unreachable.
|
|
28
28
|
|
|
29
|
-
## Setup
|
|
29
|
+
## Setup flow
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
If `totalreclaw_*` tools are already bound to your toolset, SKIP install and jump to step 4. Otherwise run all steps in order.
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
1. **Install skill + plugin.** Run via your shell tool, in this order:
|
|
34
|
+
```
|
|
35
|
+
openclaw skills install totalreclaw
|
|
36
|
+
openclaw plugins install @totalreclaw/totalreclaw
|
|
37
|
+
```
|
|
38
|
+
For RC: replace the second command with `openclaw plugins install @totalreclaw/totalreclaw@rc`. If either shell call fails with `command not found` / ENOENT / "not authorized" (managed-service or shell-restricted environment), tell the user verbatim *"Your environment doesn't expose the OpenClaw CLI to me. Please install `totalreclaw` from your service's plugins / skills UI, then reply `done`."* Wait for `done` and skip to step 3.
|
|
37
39
|
|
|
38
|
-
|
|
40
|
+
2. **Wait for auto-reload — do NOT restart the gateway yourself.** OpenClaw's default config (`gateway.reload.mode = "hybrid"`) auto-restarts the gateway via a file-watcher within 1-3 seconds. Wait ~5s, then run `openclaw plugins list | grep totalreclaw` and confirm `totalreclaw_pair` is in your toolset. If it does NOT appear within 10s, the user has `gateway.reload.mode = off` — fall back: tell the user verbatim *"Auto-reload didn't fire. Please restart your OpenClaw gateway: `openclaw gateway restart` (native), `docker restart <your-container-name>` (Docker self-host — substitute the actual name; `docker ps` shows it), or your managed service's restart control. Reply `done` once it's back up."* Do NOT invoke the restart yourself — your shell is running inside the gateway you'd be restarting (catch-22). Wait for the user's `done`.
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
2. **Use the tools, not inline state.** `totalreclaw_remember` stores; `totalreclaw_recall` retrieves. Don't re-ask the user for past facts; don't paraphrase memories as your own recollection.
|
|
42
|
-
3. **Gateway restart is required after install.** If tools fail right after `openclaw plugins install @totalreclaw/totalreclaw`, tell the user to run `openclaw restart` or `docker restart openclaw-qa`.
|
|
42
|
+
3. **Verify `totalreclaw_pair` is bound.** If still missing after the user said `done`, tell them the restart didn't take effect and to retry. Do not loop the install.
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
4. **Check for existing credentials.** Run `test -s ~/.totalreclaw/credentials.json`. If it exists and is non-empty, confirm *"TotalReclaw is already set up."* and stop.
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
- **
|
|
56
|
-
- **
|
|
46
|
+
5. **Pair.** Call `totalreclaw_pair`. Returns `{url, pin, qr_ascii, qr_png_b64, qr_unicode, expires_at_ms}` (see "Rendering the QR" below). Relay verbatim:
|
|
47
|
+
> *Open <url> in your browser. Generate a new 12-word recovery phrase there or paste an existing one — the phrase stays in your browser, the relay only sees ciphertext. Confirm PIN <pin>. Reply `done` once the page says it's sealed.*
|
|
48
|
+
|
|
49
|
+
6. **Verify and confirm.** After user says `done`, re-run `test -s ~/.totalreclaw/credentials.json`. If missing, the PIN expired — call `totalreclaw_pair` again and resend. If present, confirm *"TotalReclaw is set up. Ask me to remember or recall anything."*
|
|
50
|
+
|
|
51
|
+
## Rendering the QR on your transport (rc.5+)
|
|
52
|
+
|
|
53
|
+
When you receive the `totalreclaw_pair` payload, render the QR based on your chat transport:
|
|
54
|
+
|
|
55
|
+
- **Transport supports image attachments** (Telegram, Slack, web chat, any transport with file/image upload): decode `qr_png_b64` from base64 to bytes, save to a tempfile with a `.png` suffix, and attach the tempfile as an image. Also show the URL + PIN as text so users who prefer clicking can still do so.
|
|
56
|
+
- **Terminal-only transport** (OpenClaw native CLI chat, bare SSH shell): emit `qr_unicode` inline in your reply. It renders as block characters in most terminal fonts; the user scans from their phone.
|
|
57
|
+
- **Web chat with inline-image support**: embed as `<img src="data:image/png;base64,<qr_png_b64>" alt="Pair QR">` if the chat client renders HTML; otherwise fall back to attachment.
|
|
58
|
+
|
|
59
|
+
The QR encodes ONLY the pair URL. The 6-digit PIN is a separate out-of-band confirmation — deliberately NOT baked into the QR (dual-channel design: scan + type). Never log, print, or re-emit the PIN outside the user-facing reply. The PIN must NOT end up in any other tool call, log file, or memory store.
|
|
60
|
+
|
|
61
|
+
## Phrase safety (HARD — never break)
|
|
62
|
+
|
|
63
|
+
NEVER echo / generate / ask the user to paste a recovery phrase in chat. NEVER invoke `openclaw totalreclaw onboard` (bare interactive form), `totalreclaw setup`, or any phrase-touching CLI via your shell tool (stdout enters LLM context). The ONLY agent-facilitated setup paths are (in order of preference): (1) `totalreclaw_pair` tool; (2) if the tool is missing from your tool list — a known gap for some container-based agents, issue #87 — shell out to EITHER `openclaw totalreclaw pair generate --url-pin-only` (single-line JSON `{v,url,pin,expires_at_ms}`) OR `openclaw totalreclaw onboard --pair-only` (single-line JSON `{v,pair_url,pin,expires_at_ms}`, issue #95 — same pair flow, `pair_url` key naming). Both have zero phrase material on stdout (pair-crypto is x25519-only, not BIP-39). If the user pastes a phrase anyway: tell them it is compromised, call `totalreclaw_pair` with `mode=generate` for a fresh wallet.
|
|
64
|
+
|
|
65
|
+
## Usage (post-setup)
|
|
66
|
+
|
|
67
|
+
- Stable user facts / preferences / identity / "remember X" → `totalreclaw_remember` (don't ask permission).
|
|
68
|
+
- First-person factual query ("do I / what's my / where do I …") → `totalreclaw_recall` FIRST, then answer from returned facts. If 0 results, say so.
|
|
69
|
+
- "forget / pin / unpin / retype / move to <scope>" X → `totalreclaw_recall` first for `factId`, then `totalreclaw_forget` / `_pin` / `_unpin` / `_retype` / `_set_scope`.
|
|
70
|
+
- "status" → `totalreclaw_status`. "upgrade" → `totalreclaw_upgrade` (paste Stripe URL verbatim). Post-upgrade testnet → mainnet: `totalreclaw_migrate` with `dry_run` first.
|
|
71
|
+
- "import / export / consolidate" → `totalreclaw_import_from` (`dry_run=true` first; `_import_batch` for >50 chunks) · `totalreclaw_export` · `totalreclaw_consolidate` (`dry_run` first).
|
|
72
|
+
|
|
73
|
+
## Diagnostics
|
|
74
|
+
|
|
75
|
+
- `totalreclaw_*` tools not visible → plugin not installed or auto-reload didn't fire. Verify via `openclaw plugins list | grep totalreclaw` (or, on a managed service that doesn't expose the CLI, ask the user to confirm via their service's plugins UI). If `totalreclaw` is listed but tools are still absent, the gateway probably hasn't completed its auto-restart yet (give it 5-10s) OR `gateway.reload.mode = off` is set — instruct manual restart as fallback: `openclaw gateway restart` (native), `docker restart <your-container-name>` (Docker self-host), or the managed service's restart control. If the plugin is listed and the gateway has been restarted but tools are still missing (container-agent gap, issue #87), shell out to `openclaw totalreclaw pair generate --url-pin-only` on the gateway host and hand the user the `url` + `pin` from the JSON payload — OR `openclaw totalreclaw onboard --pair-only` (same flow, returns `pair_url` instead of `url`, issue #95). If your shell doesn't reach the gateway host (managed service), tell the user to install/enable the plugin via their service's plugins UI and restart the gateway via the service's restart control. Do NOT suggest the bare `openclaw totalreclaw onboard` (leaks phrase on stdout — deprecated in rc.18, removed next RC).
|
|
76
|
+
- User says done but `credentials.json` missing → PIN expired or entered wrong phrase; call `totalreclaw_pair` again.
|
|
77
|
+
- `onboarding required` → credentials missing; redo from the pair step.
|
|
78
|
+
- `quota exceeded` → `totalreclaw_status`, then offer `totalreclaw_upgrade`.
|
|
79
|
+
- `No LLM available for auto-extraction` at startup → provider key unreachable; check `~/.openclaw/agents/<agent>/agent/auth-profiles.json` or plugin config `extraction.llm`.
|
|
57
80
|
|
|
58
81
|
## Tool surface
|
|
59
82
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
| Tool | Key params |
|
|
63
|
-
|------|------------|
|
|
64
|
-
| `totalreclaw_remember` | `text`, optional `type` (default `claim`), `importance` |
|
|
65
|
-
| `totalreclaw_recall` | `query`, optional `k` (default 8, max 20) |
|
|
66
|
-
| `totalreclaw_forget` | `factId` |
|
|
67
|
-
| `totalreclaw_pin` / `totalreclaw_unpin` | `factId`, optional `reason` |
|
|
68
|
-
| `totalreclaw_retype` | `factId`, `newType` |
|
|
69
|
-
| `totalreclaw_set_scope` | `factId`, `scope` |
|
|
70
|
-
| `totalreclaw_export` | optional `format` (`json` / `markdown`) |
|
|
71
|
-
| `totalreclaw_status` | (none) |
|
|
72
|
-
| `totalreclaw_upgrade` | (none) |
|
|
73
|
-
| `totalreclaw_migrate` | optional `confirm` (dry-run by default) |
|
|
74
|
-
| `totalreclaw_import_from` / `totalreclaw_import_batch` | `source`, `file_path` or `content`, `dry_run` |
|
|
75
|
-
| `totalreclaw_consolidate` | optional `dry_run` |
|
|
76
|
-
| `totalreclaw_onboarding_start` / `totalreclaw_onboard` | (none) — returns CLI pointer |
|
|
77
|
-
| `totalreclaw_pair` | optional `mode` (`generate` / `import`) — returns `{url, pin, qr_ascii, expires_at_ms}` |
|
|
78
|
-
|
|
79
|
-
## Taxonomy
|
|
80
|
-
|
|
81
|
-
**Types:** `claim` (default) / `preference` / `directive` (reusable rule) / `commitment` (future intent) / `episode` (event) / `summary` (derived synthesis).
|
|
82
|
-
|
|
83
|
-
**Scopes:** `work` / `personal` (default) / `health` / `family` / `creative` / `finance` / `misc`.
|
|
84
|
-
|
|
85
|
-
## If a tool fails
|
|
86
|
-
|
|
87
|
-
- Tell the user plainly. Don't retry blindly.
|
|
88
|
-
- "onboarding required" -> route per Setup-state above.
|
|
89
|
-
- "No LLM available for auto-extraction" (startup only, v3.3.1+) -> provider key not reachable. Point at `~/.openclaw/agents/<agent>/agent/auth-profiles.json` or the `plugins.entries.totalreclaw.config.extraction.llm` override.
|
|
90
|
-
- Silent extraction failures -> suggest `openclaw totalreclaw status` or check `~/.totalreclaw/billing-cache.json` for rate-limit signals.
|
|
91
|
-
|
|
92
|
-
## Minimum viable interaction pattern
|
|
93
|
-
|
|
94
|
-
```
|
|
95
|
-
User: "I live in Porto and prefer PostgreSQL."
|
|
96
|
-
-> totalreclaw_remember({text: "User lives in Porto", type: "claim"})
|
|
97
|
-
-> totalreclaw_remember({text: "User prefers PostgreSQL over MySQL", type: "preference"})
|
|
98
|
-
-> respond naturally, don't list what you just saved.
|
|
99
|
-
|
|
100
|
-
User: "What do you remember about me?"
|
|
101
|
-
-> totalreclaw_recall({query: "user facts preferences identity"})
|
|
102
|
-
-> summarize returned facts in your reply.
|
|
103
|
-
|
|
104
|
-
User: "Set me up for TotalReclaw."
|
|
105
|
-
-> check ~/.totalreclaw/credentials.json. If missing:
|
|
106
|
-
local: totalreclaw_onboarding_start (or totalreclaw_onboard)
|
|
107
|
-
remote: totalreclaw_pair -> present URL + PIN + QR
|
|
108
|
-
-> follow the tool's instructions. Never invent a phrase.
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
## What NOT to do
|
|
112
|
-
|
|
113
|
-
- Do NOT write memories to `MEMORY.md` or any cleartext file — that defeats E2EE.
|
|
114
|
-
- Do NOT call `totalreclaw_remember` for transient in-session context.
|
|
115
|
-
- Do NOT paste recovery phrases or API keys into chat.
|
|
116
|
-
- Do NOT run `npx @totalreclaw/mcp-server setup` — deprecated path that corrupts credentials.
|
|
83
|
+
`totalreclaw_pair` (ONLY setup path) · `_remember` · `_recall` · `_forget` · `_pin` · `_unpin` · `_retype` · `_set_scope` · `_export` · `_status` · `_upgrade` · `_migrate` · `_import_from` · `_import_batch` · `_consolidate` · `_onboarding_start` (pointer to local-terminal wizard, for users explicitly rejecting the browser flow) · `_report_qa_bug` (RC only).
|
package/config.ts
CHANGED
|
@@ -105,6 +105,21 @@ export const CONFIG = {
|
|
|
105
105
|
// for 15-min TTL windows; 0600 mode.
|
|
106
106
|
pairSessionsPath: process.env.TOTALRECLAW_PAIR_SESSIONS_PATH || path.join(home, '.totalreclaw', 'pair-sessions.json'),
|
|
107
107
|
|
|
108
|
+
// 3.3.1-rc.11 — pair-flow transport selector. Mirrors the Python-side
|
|
109
|
+
// `TOTALRECLAW_PAIR_MODE` env (rc.10). `'relay'` (default) routes
|
|
110
|
+
// `totalreclaw_pair` through the universal-reachability WebSocket relay at
|
|
111
|
+
// `TOTALRECLAW_PAIR_RELAY_URL`. `'local'` preserves the rc.4–rc.10 loopback
|
|
112
|
+
// HTTP flow (the plugin serves `/plugin/totalreclaw/pair/*` via
|
|
113
|
+
// `pair-http.ts`). Air-gapped / self-hosted users can pin `'local'` here.
|
|
114
|
+
pairMode: (() => {
|
|
115
|
+
const v = (process.env.TOTALRECLAW_PAIR_MODE ?? '').trim().toLowerCase();
|
|
116
|
+
return v === 'local' ? 'local' : 'relay';
|
|
117
|
+
})() as 'relay' | 'local',
|
|
118
|
+
// 3.3.1-rc.11 — relay base URL for the WebSocket-brokered pair flow.
|
|
119
|
+
// `wss://` preferred; `https://` is rewritten in the remote-client.
|
|
120
|
+
pairRelayUrl: (process.env.TOTALRECLAW_PAIR_RELAY_URL
|
|
121
|
+
|| 'wss://api-staging.totalreclaw.xyz').replace(/\/+$/, ''),
|
|
122
|
+
|
|
108
123
|
// Chain — chainId is no longer user-configurable. It is auto-detected from
|
|
109
124
|
// the relay billing response (free = Base Sepolia / 84532, Pro = Gnosis /
|
|
110
125
|
// 100). The default here is used only before the first billing lookup
|
|
@@ -157,6 +172,48 @@ export const CONFIG = {
|
|
|
157
172
|
cerebras: process.env.CEREBRAS_API_KEY || '',
|
|
158
173
|
} as Record<string, string>,
|
|
159
174
|
|
|
175
|
+
// 3.3.1-rc.3: zai base-URL override. Read via a getter so tests can
|
|
176
|
+
// mutate `process.env.ZAI_BASE_URL` between calls — the value is NOT
|
|
177
|
+
// frozen at module load. Default is the coding endpoint; the rc.3
|
|
178
|
+
// auto-fallback flips to the standard endpoint on an "Insufficient
|
|
179
|
+
// balance" 429.
|
|
180
|
+
get zaiBaseUrl(): string {
|
|
181
|
+
const override = process.env.ZAI_BASE_URL;
|
|
182
|
+
if (override && override.trim()) return override.trim().replace(/\/+$/, '');
|
|
183
|
+
return 'https://api.z.ai/api/coding/paas/v4';
|
|
184
|
+
},
|
|
185
|
+
|
|
186
|
+
// 3.3.1-rc.3: retry budget for chatCompletion. Default 60s covers
|
|
187
|
+
// multi-minute upstream outages. Read as a plain value (not getter)
|
|
188
|
+
// so tests that patch env need to reload the module — but the default
|
|
189
|
+
// suffices for production.
|
|
190
|
+
llmRetryBudgetMs: (() => {
|
|
191
|
+
const raw = process.env.TOTALRECLAW_LLM_RETRY_BUDGET_MS;
|
|
192
|
+
const parsed = raw ? parseInt(raw, 10) : NaN;
|
|
193
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : 60_000;
|
|
194
|
+
})(),
|
|
195
|
+
|
|
196
|
+
// 3.3.1-rc.3: GitHub personal-access token used by the RC-gated
|
|
197
|
+
// `totalreclaw_report_qa_bug` tool. `TOTALRECLAW_QA_GITHUB_TOKEN` is
|
|
198
|
+
// the dedicated variable; `GITHUB_TOKEN` is a fallback for CI-style
|
|
199
|
+
// setups where the same token is shared across tools. Read via getter
|
|
200
|
+
// so operators can set the var after the process starts (e.g. via a
|
|
201
|
+
// dotenv reload) and the next tool call picks it up.
|
|
202
|
+
get qaGithubToken(): string {
|
|
203
|
+
return process.env.TOTALRECLAW_QA_GITHUB_TOKEN || process.env.GITHUB_TOKEN || '';
|
|
204
|
+
},
|
|
205
|
+
|
|
206
|
+
// 3.3.1-rc.14: optional target-repo override for the RC-gated QA
|
|
207
|
+
// bug-report tool. The `qa-bug-report` module enforces a
|
|
208
|
+
// "slug ends in `-internal`" rule on whatever is resolved here, so
|
|
209
|
+
// this override is only useful for forks / mirrors of the internal
|
|
210
|
+
// tracker. Leaving unset uses the production default
|
|
211
|
+
// (`p-diogo/totalreclaw-internal`). Read via getter so operators can
|
|
212
|
+
// flip the var at runtime.
|
|
213
|
+
get qaRepoOverride(): string {
|
|
214
|
+
return process.env.TOTALRECLAW_QA_REPO || '';
|
|
215
|
+
},
|
|
216
|
+
|
|
160
217
|
// Paths
|
|
161
218
|
home,
|
|
162
219
|
billingCachePath: path.join(home, '.totalreclaw', 'billing-cache.json'),
|