@totalreclaw/totalreclaw 3.3.4-rc.1 → 3.3.4-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/SKILL.md CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: totalreclaw
3
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.4-rc.1
4
+ version: 3.3.4-rc.2
5
5
  author: TotalReclaw Team
6
6
  license: MIT
7
7
  homepage: https://totalreclaw.xyz
package/dist/index.js CHANGED
@@ -4686,9 +4686,23 @@ const plugin = {
4686
4686
  // Background task — writes credentials.json + flips state when
4687
4687
  // the browser completes the flow. Tool handler returns
4688
4688
  // immediately so the agent can tell the user the URL + PIN.
4689
+ //
4690
+ // 3.3.4-rc.2 (Pedro QA — pair flow stuck-session) — wrap the
4691
+ // WS-await in a 60s hard timeout. The relay drops sessions on
4692
+ // `ws_close` (separately patched relay-side); without this
4693
+ // bound the background task hangs in `waitNextMessage` for the
4694
+ // full 5-minute session TTL before resolving, and downstream
4695
+ // tooling that polls the gateway for completion sees stale
4696
+ // `processing` state at 129s/159s/189s. 60s is the user-side
4697
+ // deadline we surface in chat: long enough for a slow scan-
4698
+ // and-paste, short enough that a fresh URL request is the
4699
+ // obvious next step. Structured `timed_out` error in the log
4700
+ // lets ops grep for the failure mode independently of generic
4701
+ // ws-close errors.
4702
+ const PAIR_TOOL_HARD_TIMEOUT_MS = 60_000;
4689
4703
  void (async () => {
4690
4704
  try {
4691
- await awaitPhraseUpload(remoteSession, {
4705
+ const phraseUploadPromise = awaitPhraseUpload(remoteSession, {
4692
4706
  phraseValidator: (p) => validateMnemonic(p, wordlist),
4693
4707
  completePairing: async ({ mnemonic }) => {
4694
4708
  try {
@@ -4728,7 +4742,37 @@ const plugin = {
4728
4742
  return { state: 'error', error: msg };
4729
4743
  }
4730
4744
  },
4745
+ // 3.3.4-rc.2 — also pass through to awaitPhraseUpload so its
4746
+ // internal `waitNextMessage` timer matches the outer race.
4747
+ timeoutMs: PAIR_TOOL_HARD_TIMEOUT_MS,
4748
+ });
4749
+ // 3.3.4-rc.2 — outer Promise.race guard. Resolves to a
4750
+ // sentinel ({ status: 'timed_out', ... }) so the catch
4751
+ // handler can distinguish a hard-timeout from a generic
4752
+ // ws-close error and surface it explicitly.
4753
+ const TIMEOUT_SENTINEL = {
4754
+ status: 'timed_out',
4755
+ message: `Pair flow timed out (${PAIR_TOOL_HARD_TIMEOUT_MS / 1000}s) — generate a new URL with totalreclaw_pair.`,
4756
+ };
4757
+ let hardTimer;
4758
+ const hardTimeoutPromise = new Promise((resolve) => {
4759
+ hardTimer = setTimeout(() => resolve(TIMEOUT_SENTINEL), PAIR_TOOL_HARD_TIMEOUT_MS);
4731
4760
  });
4761
+ try {
4762
+ const raced = await Promise.race([
4763
+ phraseUploadPromise,
4764
+ hardTimeoutPromise,
4765
+ ]);
4766
+ if (raced &&
4767
+ typeof raced === 'object' &&
4768
+ raced.status === 'timed_out') {
4769
+ api.logger.warn(`totalreclaw_pair(relay): hard timeout — ${raced.message} (token=${remoteSession.token.slice(0, 8)}…)`);
4770
+ }
4771
+ }
4772
+ finally {
4773
+ if (hardTimer)
4774
+ clearTimeout(hardTimer);
4775
+ }
4732
4776
  }
4733
4777
  catch (bgErr) {
4734
4778
  // Expected on TTL expiry / user-aborts — log at warn, not error.
@@ -44,7 +44,7 @@
44
44
  * `CONFIG`. See `index.ts` wire-up.
45
45
  */
46
46
  import { validateMnemonic } from '@scure/bip39';
47
- import { wordlist } from '@scure/bip39/wordlists/english';
47
+ import { wordlist } from '@scure/bip39/wordlists/english.js';
48
48
  import { loadCredentialsJson, writeCredentialsJson, writeOnboardingState, } from './fs-helpers.js';
49
49
  import { awaitPhraseUpload, openRemotePairSession, } from './pair-remote-client.js';
50
50
  import { setRecoveryPhraseOverride } from './config.js';
package/index.ts CHANGED
@@ -5496,9 +5496,23 @@ const plugin = {
5496
5496
  // Background task — writes credentials.json + flips state when
5497
5497
  // the browser completes the flow. Tool handler returns
5498
5498
  // immediately so the agent can tell the user the URL + PIN.
5499
+ //
5500
+ // 3.3.4-rc.2 (Pedro QA — pair flow stuck-session) — wrap the
5501
+ // WS-await in a 60s hard timeout. The relay drops sessions on
5502
+ // `ws_close` (separately patched relay-side); without this
5503
+ // bound the background task hangs in `waitNextMessage` for the
5504
+ // full 5-minute session TTL before resolving, and downstream
5505
+ // tooling that polls the gateway for completion sees stale
5506
+ // `processing` state at 129s/159s/189s. 60s is the user-side
5507
+ // deadline we surface in chat: long enough for a slow scan-
5508
+ // and-paste, short enough that a fresh URL request is the
5509
+ // obvious next step. Structured `timed_out` error in the log
5510
+ // lets ops grep for the failure mode independently of generic
5511
+ // ws-close errors.
5512
+ const PAIR_TOOL_HARD_TIMEOUT_MS = 60_000;
5499
5513
  void (async () => {
5500
5514
  try {
5501
- await awaitPhraseUpload(remoteSession, {
5515
+ const phraseUploadPromise = awaitPhraseUpload(remoteSession, {
5502
5516
  phraseValidator: (p: string) =>
5503
5517
  validateMnemonic(p, wordlist),
5504
5518
  completePairing: async ({ mnemonic }) => {
@@ -5546,7 +5560,48 @@ const plugin = {
5546
5560
  return { state: 'error', error: msg };
5547
5561
  }
5548
5562
  },
5563
+ // 3.3.4-rc.2 — also pass through to awaitPhraseUpload so its
5564
+ // internal `waitNextMessage` timer matches the outer race.
5565
+ timeoutMs: PAIR_TOOL_HARD_TIMEOUT_MS,
5549
5566
  });
5567
+ // 3.3.4-rc.2 — outer Promise.race guard. Resolves to a
5568
+ // sentinel ({ status: 'timed_out', ... }) so the catch
5569
+ // handler can distinguish a hard-timeout from a generic
5570
+ // ws-close error and surface it explicitly.
5571
+ const TIMEOUT_SENTINEL: {
5572
+ status: 'timed_out';
5573
+ message: string;
5574
+ } = {
5575
+ status: 'timed_out',
5576
+ message:
5577
+ `Pair flow timed out (${PAIR_TOOL_HARD_TIMEOUT_MS / 1000}s) — generate a new URL with totalreclaw_pair.`,
5578
+ };
5579
+ let hardTimer: ReturnType<typeof setTimeout> | undefined;
5580
+ const hardTimeoutPromise = new Promise<typeof TIMEOUT_SENTINEL>(
5581
+ (resolve) => {
5582
+ hardTimer = setTimeout(
5583
+ () => resolve(TIMEOUT_SENTINEL),
5584
+ PAIR_TOOL_HARD_TIMEOUT_MS,
5585
+ );
5586
+ },
5587
+ );
5588
+ try {
5589
+ const raced = await Promise.race([
5590
+ phraseUploadPromise,
5591
+ hardTimeoutPromise,
5592
+ ]);
5593
+ if (
5594
+ raced &&
5595
+ typeof raced === 'object' &&
5596
+ (raced as { status?: unknown }).status === 'timed_out'
5597
+ ) {
5598
+ api.logger.warn(
5599
+ `totalreclaw_pair(relay): hard timeout — ${(raced as typeof TIMEOUT_SENTINEL).message} (token=${remoteSession.token.slice(0, 8)}…)`,
5600
+ );
5601
+ }
5602
+ } finally {
5603
+ if (hardTimer) clearTimeout(hardTimer);
5604
+ }
5550
5605
  } catch (bgErr: unknown) {
5551
5606
  // Expected on TTL expiry / user-aborts — log at warn, not error.
5552
5607
  const bgMsg = bgErr instanceof Error ? bgErr.message : String(bgErr);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@totalreclaw/totalreclaw",
3
- "version": "3.3.4-rc.1",
3
+ "version": "3.3.4-rc.2",
4
4
  "description": "End-to-end encrypted, agent-portable memory for OpenClaw and any LLM-agent runtime. XChaCha20-Poly1305 with protobuf v4 + on-chain Memory Taxonomy v1 (claim / preference / directive / commitment / episode / summary).",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -31,6 +31,7 @@
31
31
  "author": "TotalReclaw Team",
32
32
  "license": "MIT",
33
33
  "dependencies": {
34
+ "@scure/bip39": "^2.2.0",
34
35
  "@totalreclaw/client": "^1.2.0",
35
36
  "@totalreclaw/core": "^2.1.1",
36
37
  "@types/qrcode": "^1.5.6",
package/pair-cli-relay.ts CHANGED
@@ -45,7 +45,7 @@
45
45
  */
46
46
 
47
47
  import { validateMnemonic } from '@scure/bip39';
48
- import { wordlist } from '@scure/bip39/wordlists/english';
48
+ import { wordlist } from '@scure/bip39/wordlists/english.js';
49
49
 
50
50
  import {
51
51
  loadCredentialsJson,
package/skill.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "totalreclaw",
3
- "version": "3.3.4-rc.1",
3
+ "version": "3.3.4-rc.2",
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",