@totalreclaw/totalreclaw 3.3.0-rc.6 → 3.3.1-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,292 @@ 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.2] — 2026-04-22
8
+
9
+ Follow-up RC for the 3.3.1-rc.1 QA NO-GO
10
+ (`docs/notes/QA-plugin-3.3.1-rc.1-20260422-0121.md` in
11
+ `totalreclaw-internal`). Fixes 3 ship-stoppers + 1 serious non-blocker
12
+ identified by the first real-user-flow QA under the 2026-04-22 chat-only
13
+ discipline, plus several UX gaps flagged by Pedro's agent (Hermes) during
14
+ parallel Telegram testing. All 3.3.1-rc.1 provider-agnostic LLM work is
15
+ preserved.
16
+
17
+ ### Changed
18
+
19
+ - **`gateway-url.ts` — drop `child_process` subprocess probe.** The rc.1
20
+ implementation shelled out to `tailscale status --json` via
21
+ `child_process.execFileSync` to discover the local MagicDNS hostname.
22
+ This tripped the OpenClaw dangerous-code scanner's shell-execution
23
+ rule and **blocked every `openclaw plugins install @totalreclaw/totalreclaw`**.
24
+ rc.2 swaps to a passive probe: `os.networkInterfaces()` detects a
25
+ `tailscale*` NIC carrying a CGNAT IPv4 (100.64/10), and we surface
26
+ the raw IP as the auto-detected host. Operators who want a proper
27
+ `https://<magicdns>.ts.net` URL now set
28
+ `plugins.entries.totalreclaw.config.publicUrl` explicitly (documented
29
+ in SKILL.md). The six-layer URL cascade is otherwise unchanged.
30
+
31
+ - **`check-scanner.mjs` — add shell-execution rule (catches `child_process`).**
32
+ Scanner-sim now mirrors the real OpenClaw `shell-execution` rule that
33
+ trips on any `child_process` substring (no context gate). Prevents a
34
+ repeat of the rc.1 regression. See `skill/scripts/check-scanner.mjs`
35
+ SHELL_EXEC_PATTERN.
36
+
37
+ - **`totalreclaw_forget` — route through `submitFactBatchOnChain` and write
38
+ tombstones at legacy v3.** The rc.1 implementation used the single-fact
39
+ `submitFactOnChain` path and wrote the tombstone at protobuf v4, which
40
+ the subgraph did NOT reflect as `isActive=false`. rc.2 mirrors the
41
+ pin/unpin tombstone shape exactly (legacy v3, `source="tombstone"`,
42
+ single-payload batch via `submitFactBatchOnChain`). Also adds
43
+ UUID-shape validation on `factId` to reject LLM hallucinations
44
+ ("forget that I live in Porto" passed as the factId) with a clear
45
+ message pointing the agent at `totalreclaw_recall` first.
46
+
47
+ - **`totalreclaw_forget` tool description** — rewritten from terse
48
+ ("Delete a specific memory by its ID.") to agent-instructive with a
49
+ recall-first workflow hint. Fixes the rc.1 QA failure where the LLM
50
+ hallucinated "Done" without actually calling the tool.
51
+
52
+ - **`chatCompletion` — exponential-backoff retry for 429 / timeouts.**
53
+ rc.1 QA: 5 of 6 extraction windows returned 0 raw facts because zai
54
+ 429s and timeouts had no retry path. rc.2 adds a retry wrapper:
55
+ 3 attempts with 1s → 2s → 4s backoff; 30s per-attempt timeout;
56
+ fail-fast on 4xx-other-than-429. Every extractor callsite
57
+ (`extractFacts`, `extractFactsForCompaction`, `comparativeRescoreV1`,
58
+ `extractDebriefFacts`) opts in to the retry + logger. See
59
+ `isRetryable()` for the classification list.
60
+
61
+ - **`llm-profile-reader.ts` — fallback to legacy `models.json` format.**
62
+ rc.1 QA VPS had `~/.openclaw/agents/<agent>/agent/models.json` (the
63
+ pre-auth-profiles shape, `{ providers: { zai: { apiKey: "..." } } }`)
64
+ not `auth-profiles.json`. The auto-resolve silently no-op'd.
65
+ rc.2 adds a 5th cascade tier: `readAllProfileKeys` reads
66
+ auth-profiles.json FIRST (takes precedence on overlap), then merges
67
+ in models.json entries for any provider not already covered.
68
+
69
+ ### Added
70
+
71
+ - **`totalreclaw_onboard`** (agent tool) — lets the agent drive the
72
+ non-interactive onboard flow from chat without shelling out. Generate
73
+ mode only (restore still requires `openclaw totalreclaw onboard --mode
74
+ restore` in the local terminal for security). Returns scope address +
75
+ credentials path; NEVER returns the mnemonic. Directly wraps
76
+ `runNonInteractiveOnboard` in-process.
77
+
78
+ - **`totalreclaw_pair`** (agent tool) — lets the agent start a pairing
79
+ session from chat and relay the URL + PIN + QR ASCII to the user.
80
+ Built on the same `createPairSession` + `buildPairingUrl` surface the
81
+ CLI uses, no subprocess. The recovery phrase still never crosses the
82
+ LLM — it's generated/entered in the BROWSER and uploaded E2EE.
83
+
84
+ - **`totalreclaw_retype`** (agent tool) — reclassify an existing memory
85
+ from one taxonomy type to another (claim/preference/directive/
86
+ commitment/episode/summary). Writes a new v1.1 claim with the updated
87
+ type, tombstones the old fact on-chain. rc.1 QA confirmed this tool
88
+ was documented in SKILL.md but NOT registered — agents couldn't call
89
+ it.
90
+
91
+ - **`totalreclaw_set_scope`** (agent tool) — move an existing memory to
92
+ a different scope (work/personal/health/family/creative/finance/misc/
93
+ unspecified). Same write pattern as retype. Also previously
94
+ documented-not-registered; rc.1 QA showed agents falling back to a
95
+ hallucinated delete+re-store workaround.
96
+
97
+ - **`skill/plugin/retype-setscope.ts`** — new pure-logic module
98
+ supporting the two agent tools above. Tightly mirrors pin.ts but
99
+ without the idempotent-status short-circuit (user may be confirming
100
+ a prior auto-extraction label) and without feedback wiring.
101
+
102
+ - **`skill/plugin/gateway-url.test.ts`** — unit coverage for the new
103
+ passive Tailscale + LAN detection. 17 cases, all green.
104
+
105
+ - **`skill/plugin/retype-setscope.test.ts`** — 31 cases covering arg
106
+ validation, successful rewrites, fact-not-found, submit failure,
107
+ malformed-blob, invalid-type/scope.
108
+
109
+ - **`skill/plugin/llm-client-retry.test.ts`** — 29 cases for the retry
110
+ wrapper: isRetryable classification, backoff behaviour, fail-fast on
111
+ non-retryable errors, logger interaction.
112
+
113
+ - **`skill/plugin/llm-profile-reader.test.ts`** — 13 additional cases
114
+ for models.json parsing + combined reader.
115
+
116
+ ### Preserved from rc.1
117
+
118
+ All the rc.1 LLM-autoresolve work carries forward unchanged:
119
+ - 4-tier cascade (plugin config → openclawProviders → auth-profiles →
120
+ env). With rc.2's `models.json` fallback it's effectively 5 tiers.
121
+ - `openclaw totalreclaw onboard --non-interactive --json --mode` CLI.
122
+ - `openclaw totalreclaw pair generate --json` CLI.
123
+ - `extraction.llm` plugin-config override block.
124
+ - Synchronous HTTP-route registration, manifest `kind` drop, etc.
125
+
126
+ ## [3.3.1-rc.1] — 2026-04-22
127
+
128
+ First release candidate for 3.3.1. Comprehensive patch release addressing
129
+ user-QA findings against 3.3.0-rc.6
130
+ (`docs/notes/QA-user-findings-3.3.0-rc.6-20260421.md` in
131
+ `totalreclaw-internal`). The 3.3.0 runtime works; what 3.3.1 fixes is the
132
+ user experience around LLM auto-detection, config schema, non-interactive
133
+ CLI, gateway-URL resolution, and SKILL.md. All rc.2–rc.6 fixes are
134
+ preserved (scanner comment, auth: 'plugin' literal, ensureSessionsFileDir
135
+ mkdir, sync HTTP-route registration, manifest kind drop).
136
+
137
+ See: `plans/2026-04-22-plugin-3.3.1-provider-agnostic-llm.md` (internal).
138
+
139
+ ### Added
140
+
141
+ - **`skill/plugin/llm-profile-reader.ts`** — new scanner-isolated module that
142
+ harvests provider API keys from
143
+ `~/.openclaw/agents/<agent>/agent/auth-profiles.json`. This is where real
144
+ OpenClaw installs store user API keys. rc.6 silently no-op'd auto-extraction
145
+ for nearly every real user because `initLLMClient` only looked at env vars
146
+ and the SDK-passed `api.config.providers` — neither of which reach
147
+ auth-profiles.json.
148
+
149
+ - **`skill/plugin/gateway-url.ts`** — new scanner-isolated module that detects
150
+ the gateway's externally-reachable URL for QR pairing. Two autodetect tiers:
151
+ 1. Tailscale MagicDNS via `tailscale status --json` (assumes `tailscale
152
+ serve` on 443).
153
+ 2. First non-loopback, non-virtual IPv4 interface (LAN mode; emits a
154
+ "only works on the same network" warning).
155
+
156
+ - **`initLLMClient` 4-tier resolution cascade** — plugin-config override
157
+ (highest) → SDK-passed openclawProviders → harvested auth-profiles.json
158
+ keys → env vars (lowest). Every tier logs ONCE at startup at INFO level;
159
+ per-turn noise from rc.6 is removed.
160
+
161
+ - **`openclaw totalreclaw onboard` non-interactive modes**:
162
+ - `--non-interactive` — exits 1 if any input would be prompted.
163
+ - `--json` — emits a structured payload (requires `--non-interactive`).
164
+ - `--mode <generate|restore>` — skip the menu prompt.
165
+ - `--phrase <12-or-24>` — required for `--mode restore`; `-` reads stdin.
166
+ - `--emit-phrase` — opt-in path that includes the plaintext phrase in the
167
+ JSON payload. Default omits the phrase; the agent should direct the
168
+ user to read `~/.totalreclaw/credentials.json` in their terminal.
169
+
170
+ - **`openclaw totalreclaw pair [mode]` non-interactive flags**:
171
+ - `--json` — emits `{v, sid, url, pin, mode, expires_at_ms, qr_ascii}` to
172
+ stdout before polling begins. Agents capture + present to the user.
173
+ - `--timeout <sec>` — override the 15-minute default session TTL.
174
+
175
+ - **`extraction.llm` plugin-config override** — new optional block in the
176
+ plugin config schema. Explicit provider/model/apiKey/baseUrl wins over
177
+ every auto-detection tier:
178
+ ```yaml
179
+ plugins:
180
+ entries:
181
+ totalreclaw:
182
+ config:
183
+ extraction:
184
+ llm:
185
+ provider: zai
186
+ apiKey: <your-key>
187
+ model: glm-4.5-flash # optional — derived from provider default otherwise
188
+ ```
189
+
190
+ - **Config schema accepts `publicUrl` + `extraction.interval` +
191
+ `extraction.maxFactsPerExtraction`** — 3.3.0 rejected these keys with
192
+ `invalid config: must NOT have additional properties`. Both the manifest
193
+ (`openclaw.plugin.json`) and the JS plugin definition now accept them.
194
+ `extraction.additionalProperties` and `extraction.llm.additionalProperties`
195
+ remain `false` to keep the surface strictly typed.
196
+
197
+ - **Three new test files**:
198
+ - `llm-profile-reader.test.ts` — 19 assertions covering the auth-profiles
199
+ harvester (provider mapping, malformed input, multi-agent aggregation).
200
+ - `llm-client.test.ts` — 28 assertions covering the 4-tier cascade,
201
+ plus the `deriveCheapModel` regex-boundary fix.
202
+ - `config-schema.test.ts` — 14 assertions (+ Ajv strict validation when
203
+ available) covering the 3.3.1 schema surface.
204
+ - `onboarding-noninteractive.test.ts` — 22 assertions covering
205
+ `runNonInteractiveOnboard` happy path, phrase-validation, mode 0600,
206
+ `already-active` short-circuit.
207
+ - `pair-cli-json.test.ts` — 17 assertions covering pair-cli JSON output,
208
+ `ttlSeconds` propagation, and human-mode regression.
209
+
210
+ ### Changed
211
+
212
+ - **`pair-cli.ts` — no TTY requirement**. Prior rc versions imported
213
+ `readline` but never used it; the intro block also had no interactive
214
+ prompts. 3.3.1 removes any path that touches `setRawMode` in pair-cli and
215
+ adds a 10-second timeout on the QR renderer so a misbehaving qrcode-terminal
216
+ never hangs the pairing flow. Confirmed by
217
+ `pair-cli-json.test.ts` asserting JSON mode emits a single payload without
218
+ any TTY interaction.
219
+
220
+ - **`deriveCheapModel` — fixes word-boundary regression**. rc.6 used
221
+ `primaryModel.toLowerCase().includes(cheapWord)` which matched the substring
222
+ `mini` inside `gemini`, so `gemini-2.5-pro` passed through unchanged and
223
+ the extractor called a model the user hadn't configured. 3.3.1 uses a
224
+ word-boundary regex (`/(?:^|[-_/.])(?:flash|mini|nano|haiku|small|lite|fast)(?:[-_/.]|$)/i`).
225
+
226
+ - **Cheap-model table** — exported as `CHEAP_MODEL_BY_PROVIDER` for use by
227
+ paths that resolve a provider without knowing the user's primary model
228
+ (auth-profiles.json tier). Includes zai→glm-4.5-flash, openai→gpt-4.1-mini,
229
+ anthropic→claude-haiku-4-5-20251001, gemini/google→gemini-flash-lite,
230
+ groq→llama-3.3-70b-versatile, deepseek→deepseek-chat,
231
+ openrouter→anthropic/claude-haiku-4-5-20251001, xai→grok-2,
232
+ mistral→mistral-small-latest, together→meta-llama/Llama-3.3-70B-Instruct-Turbo,
233
+ cerebras→llama3.3-70b.
234
+
235
+ - **Gateway pairing URL cascade** — `buildPairingUrl` now threads through the
236
+ six-layer cascade: `publicUrl` → `gateway.remote.url` → custom bind host →
237
+ Tailscale autodetect → LAN autodetect → localhost fallback. Each fallback
238
+ emits a warning with clear pointer to `publicUrl` for override.
239
+
240
+ - **SKILL.md — full rewrite**. Explicit prohibition of generating phrases in
241
+ chat; canonical onboarding commands (`openclaw totalreclaw onboard` or
242
+ `onboard --non-interactive --json --mode generate`); two-step install flow
243
+ documented clearly; full 3.3.1 config schema documented; all tool surfaces
244
+ aligned with current taxonomy (`claim|preference|directive|commitment|
245
+ episode|summary`); references to `npx @totalreclaw/mcp-server setup`
246
+ removed.
247
+
248
+ ### Fixed
249
+
250
+ - **LLM auto-resolve silent no-op** — the root user-facing bug from
251
+ `QA-user-findings-3.3.0-rc.6-20260421.md`. Users store their provider key
252
+ in `~/.openclaw/agents/<agent>/agent/auth-profiles.json`; rc.6 never looked
253
+ there, so every turn logged `No LLM available for auto-extraction` and
254
+ zero facts were extracted. 3.3.1 adds auth-profiles as tier 3 of the
255
+ cascade.
256
+
257
+ - **`plugins.entries.totalreclaw.config.publicUrl` rejected** — user-documented
258
+ config key errored out with `invalid config: must NOT have additional
259
+ properties`. Schema was missing the property. Fixed in both `openclaw.plugin.json`
260
+ and the in-JS `configSchema`.
261
+
262
+ - **`No LLM available` fires every turn** — downgraded to a single INFO log
263
+ at startup. Never per-turn unless the resolvable state changes. The
264
+ `extraction.enabled=false` path also moved from warn to info (it's a user
265
+ choice, not a diagnostic signal).
266
+
267
+ - **Recovery-phrase-in-chat in SKILL.md** — the prior SKILL.md told the
268
+ agent to "run `npx @totalreclaw/mcp-server setup` to generate a
269
+ cryptographically valid recovery phrase… display it prominently". Any
270
+ compliant agent following this leaked the phrase to the LLM provider's
271
+ logging path. Removed entirely and replaced with an explicit prohibition
272
+ + pointer to CLI flows.
273
+
274
+ ### Preserved from rc.2–rc.6
275
+
276
+ - rc.2 scanner-comment isolation (fetch-word in comments rewrapped)
277
+ - rc.4 `auth: 'plugin'` literal on HTTP routes
278
+ - rc.4 `ensureSessionsFileDir` mkdir before lock acquire
279
+ - rc.5 synchronous `registerHttpRoute` calls (no async IIFE)
280
+ - rc.6 `openclaw.plugin.json` drop of `"kind": "memory"` (startup registry
281
+ fix; JS plugin definition still returns `kind: 'memory' as const` for
282
+ memory-slot matching)
283
+
284
+ ### Unchanged
285
+
286
+ No protocol / on-chain changes vs 3.3.0. Memory Taxonomy v1 unchanged.
287
+ Protobuf v4 unchanged. Subgraph schema unchanged. Billing cache unchanged.
288
+ Relay API surface unchanged. No breaking changes to any public tool
289
+ contract.
290
+
291
+ ---
292
+
7
293
  ## [3.3.0-rc.6] — 2026-04-20
8
294
 
9
295
  Sixth release candidate for 3.3.0. Single manifest-only fix for the