@totalreclaw/totalreclaw 1.0.3 → 1.0.4
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/README.md +1 -0
- package/SKILL.md +23 -1
- package/dist/index.js +57 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -46,6 +46,7 @@ TotalReclaw also ships a standalone MCP server for Claude Desktop, Cursor, and o
|
|
|
46
46
|
| `totalreclaw_forget` | Delete a specific memory (on-chain tombstone) |
|
|
47
47
|
| `totalreclaw_export` | Export all memories as plaintext |
|
|
48
48
|
| `totalreclaw_status` | Check subscription tier and quota |
|
|
49
|
+
| `totalreclaw_generate_recovery_phrase` | Generate a secure 12-word BIP-39 mnemonic (onboarding) |
|
|
49
50
|
|
|
50
51
|
## Lifecycle hooks
|
|
51
52
|
|
package/SKILL.md
CHANGED
|
@@ -208,6 +208,28 @@ Check subscription status and usage quota.
|
|
|
208
208
|
|
|
209
209
|
---
|
|
210
210
|
|
|
211
|
+
### totalreclaw_generate_recovery_phrase
|
|
212
|
+
|
|
213
|
+
Generate a cryptographically secure 12-word BIP-39 recovery phrase for new users. **Always use this tool** — never generate mnemonic words yourself.
|
|
214
|
+
|
|
215
|
+
**Parameters:** None
|
|
216
|
+
|
|
217
|
+
**Example:**
|
|
218
|
+
```json
|
|
219
|
+
{}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**Returns:**
|
|
223
|
+
```json
|
|
224
|
+
{
|
|
225
|
+
"mnemonic": "abandon ability able about above absent absorb abstract absurd abuse access accident",
|
|
226
|
+
"wordCount": 12,
|
|
227
|
+
"instructions": ["Display this phrase prominently to the user.", "..."]
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
211
233
|
## Post-Install Setup
|
|
212
234
|
|
|
213
235
|
After installing TotalReclaw, the agent MUST complete setup automatically. **Do NOT ask the user to set environment variables manually.**
|
|
@@ -227,7 +249,7 @@ The master password is a **12-word BIP-39 mnemonic** — like a crypto wallet se
|
|
|
227
249
|
Ask the user:
|
|
228
250
|
> "Do you have an existing TotalReclaw recovery phrase you'd like to restore, or should I generate a new one?"
|
|
229
251
|
|
|
230
|
-
- **New user:**
|
|
252
|
+
- **New user:** Call the `totalreclaw_generate_recovery_phrase` tool to generate a cryptographically secure 12-word BIP-39 mnemonic. **NEVER generate mnemonic words yourself** — always use this tool. Then set it as `TOTALRECLAW_MASTER_PASSWORD` and display it prominently with a warning:
|
|
231
253
|
> "⚠️ SAVE YOUR RECOVERY PHRASE — it's the only way to recover your memories if you switch devices: `[phrase]`"
|
|
232
254
|
- **Returning user:** Ask them to provide their existing 12-word phrase, then set it as `TOTALRECLAW_MASTER_PASSWORD`.
|
|
233
255
|
|
package/dist/index.js
CHANGED
|
@@ -9758,6 +9758,12 @@ function createHasher(hashCons, info = {}) {
|
|
|
9758
9758
|
Object.assign(hashC, info);
|
|
9759
9759
|
return Object.freeze(hashC);
|
|
9760
9760
|
}
|
|
9761
|
+
function randomBytes(bytesLength = 32) {
|
|
9762
|
+
const cr = typeof globalThis === "object" ? globalThis.crypto : null;
|
|
9763
|
+
if (typeof cr?.getRandomValues !== "function")
|
|
9764
|
+
throw new Error("crypto.getRandomValues must be defined");
|
|
9765
|
+
return cr.getRandomValues(new Uint8Array(bytesLength));
|
|
9766
|
+
}
|
|
9761
9767
|
var oidNist = (suffix) => ({
|
|
9762
9768
|
oid: Uint8Array.from([6, 9, 96, 134, 72, 1, 101, 3, 4, 2, suffix])
|
|
9763
9769
|
});
|
|
@@ -11512,6 +11518,7 @@ var utils = {
|
|
|
11512
11518
|
};
|
|
11513
11519
|
|
|
11514
11520
|
// node_modules/@scure/bip39/index.js
|
|
11521
|
+
var isJapanese = (wordlist2) => wordlist2[0] === "\u3042\u3044\u3053\u304F\u3057\u3093";
|
|
11515
11522
|
function nfkd(str) {
|
|
11516
11523
|
if (typeof str !== "string")
|
|
11517
11524
|
throw new TypeError("invalid mnemonic type: " + typeof str);
|
|
@@ -11529,6 +11536,12 @@ function aentropy(ent) {
|
|
|
11529
11536
|
if (![16, 20, 24, 28, 32].includes(ent.length))
|
|
11530
11537
|
throw new Error("invalid entropy length");
|
|
11531
11538
|
}
|
|
11539
|
+
function generateMnemonic(wordlist2, strength = 128) {
|
|
11540
|
+
anumber(strength);
|
|
11541
|
+
if (strength % 32 !== 0 || strength > 256)
|
|
11542
|
+
throw new TypeError("Invalid entropy");
|
|
11543
|
+
return entropyToMnemonic(randomBytes(strength / 8), wordlist2);
|
|
11544
|
+
}
|
|
11532
11545
|
var calcChecksum = (entropy) => {
|
|
11533
11546
|
const bitsLeft = 8 - entropy.length / 4;
|
|
11534
11547
|
return new Uint8Array([sha256(entropy)[0] >> bitsLeft << bitsLeft]);
|
|
@@ -11548,6 +11561,11 @@ function mnemonicToEntropy(mnemonic, wordlist2) {
|
|
|
11548
11561
|
aentropy(entropy);
|
|
11549
11562
|
return entropy;
|
|
11550
11563
|
}
|
|
11564
|
+
function entropyToMnemonic(entropy, wordlist2) {
|
|
11565
|
+
aentropy(entropy);
|
|
11566
|
+
const words = getCoder(wordlist2).encode(entropy);
|
|
11567
|
+
return words.join(isJapanese(wordlist2) ? "\u3000" : " ");
|
|
11568
|
+
}
|
|
11551
11569
|
function validateMnemonic(mnemonic, wordlist2) {
|
|
11552
11570
|
try {
|
|
11553
11571
|
mnemonicToEntropy(mnemonic, wordlist2);
|
|
@@ -13629,6 +13647,9 @@ function isBip39Mnemonic(input) {
|
|
|
13629
13647
|
if (words.length !== 12 && words.length !== 24) return false;
|
|
13630
13648
|
return validateMnemonic(input.trim(), wordlist);
|
|
13631
13649
|
}
|
|
13650
|
+
function generateSecureMnemonic() {
|
|
13651
|
+
return generateMnemonic(wordlist, 128);
|
|
13652
|
+
}
|
|
13632
13653
|
function deriveKeysFromMnemonic(mnemonic) {
|
|
13633
13654
|
const seed = mnemonicToSeedSync(mnemonic.trim());
|
|
13634
13655
|
const salt = Buffer.from(seed.slice(0, 32));
|
|
@@ -30952,7 +30973,7 @@ async function initialize(logger) {
|
|
|
30952
30973
|
}
|
|
30953
30974
|
}
|
|
30954
30975
|
}
|
|
30955
|
-
var SETUP_ERROR_MSG = 'TotalReclaw setup required. Follow the "Post-Install Setup" steps in SKILL.md:\n1. Set TOTALRECLAW_MASTER_PASSWORD \u2014 ask the user if they have an existing recovery phrase or generate a
|
|
30976
|
+
var SETUP_ERROR_MSG = 'TotalReclaw setup required. Follow the "Post-Install Setup" steps in SKILL.md:\n1. Set TOTALRECLAW_MASTER_PASSWORD \u2014 ask the user if they have an existing recovery phrase, or call totalreclaw_generate_recovery_phrase to generate a secure one.\n2. Set TOTALRECLAW_SUBGRAPH_MODE=true\n3. Restart the gateway to apply changes.';
|
|
30956
30977
|
async function ensureInitialized(logger) {
|
|
30957
30978
|
if (!initPromise) {
|
|
30958
30979
|
initPromise = initialize(logger);
|
|
@@ -31688,6 +31709,40 @@ ${lines.join("\n")}`;
|
|
|
31688
31709
|
},
|
|
31689
31710
|
{ name: "totalreclaw_status" }
|
|
31690
31711
|
);
|
|
31712
|
+
api.registerTool(
|
|
31713
|
+
{
|
|
31714
|
+
name: "totalreclaw_generate_recovery_phrase",
|
|
31715
|
+
label: "Generate Recovery Phrase",
|
|
31716
|
+
description: "Generate a cryptographically secure 12-word BIP-39 recovery phrase. Call this during onboarding when the user needs a new recovery phrase. NEVER generate mnemonics yourself \u2014 always use this tool.",
|
|
31717
|
+
parameters: {
|
|
31718
|
+
type: "object",
|
|
31719
|
+
properties: {},
|
|
31720
|
+
additionalProperties: false
|
|
31721
|
+
},
|
|
31722
|
+
execute() {
|
|
31723
|
+
const mnemonic = generateSecureMnemonic();
|
|
31724
|
+
return {
|
|
31725
|
+
content: [
|
|
31726
|
+
{
|
|
31727
|
+
type: "text",
|
|
31728
|
+
text: JSON.stringify({
|
|
31729
|
+
mnemonic,
|
|
31730
|
+
wordCount: 12,
|
|
31731
|
+
instructions: [
|
|
31732
|
+
"Display this phrase prominently to the user.",
|
|
31733
|
+
"Warn them to save it \u2014 it is the ONLY way to recover their memories.",
|
|
31734
|
+
"Set it as TOTALRECLAW_MASTER_PASSWORD in the OpenClaw config.",
|
|
31735
|
+
"Set TOTALRECLAW_SUBGRAPH_MODE=true.",
|
|
31736
|
+
"Restart the gateway to apply changes."
|
|
31737
|
+
]
|
|
31738
|
+
})
|
|
31739
|
+
}
|
|
31740
|
+
]
|
|
31741
|
+
};
|
|
31742
|
+
}
|
|
31743
|
+
},
|
|
31744
|
+
{ name: "totalreclaw_generate_recovery_phrase" }
|
|
31745
|
+
);
|
|
31691
31746
|
api.on(
|
|
31692
31747
|
"before_agent_start",
|
|
31693
31748
|
async (event) => {
|
|
@@ -31700,7 +31755,7 @@ ${lines.join("\n")}`;
|
|
|
31700
31755
|
await ensureInitialized(api.logger);
|
|
31701
31756
|
if (needsSetup) {
|
|
31702
31757
|
return {
|
|
31703
|
-
prependContext: '## TotalReclaw Setup Required\n\nTotalReclaw is installed but needs configuration. Follow the "Post-Install Setup" steps in SKILL.md to complete setup.\nAsk the user: "Do you have an existing TotalReclaw recovery phrase, or should I generate a new one?"'
|
|
31758
|
+
prependContext: '## TotalReclaw Setup Required\n\nTotalReclaw is installed but needs configuration. Follow the "Post-Install Setup" steps in SKILL.md to complete setup.\nAsk the user: "Do you have an existing TotalReclaw recovery phrase, or should I generate a new one?"\nIf they want a new one, call the `totalreclaw_generate_recovery_phrase` tool \u2014 NEVER generate mnemonic words yourself.'
|
|
31704
31759
|
};
|
|
31705
31760
|
}
|
|
31706
31761
|
let billingWarning = "";
|