mnemospark 1.4.0 → 1.6.0

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 CHANGED
@@ -31,23 +31,15 @@ openclaw gateway start
31
31
  > Plugin registration is done by `openclaw plugins install mnemospark`.
32
32
  > The install also bundles the `skills/mnemospark` skill package so the main agent can delegate mnemospark workflows.
33
33
 
34
- ### 2) (Optional) Initialize wallet helpers
35
-
36
- ```bash
37
- npx mnemospark install --standard
38
- ```
39
-
40
- This creates/reuses local wallet helper files under `~/.openclaw/mnemospark/`.
41
-
42
- ### 3) Restart gateway after updates
34
+ ### 2) Restart gateway after updates
43
35
 
44
36
  ```bash
45
37
  openclaw gateway restart
46
38
  ```
47
39
 
48
- ### 4) Use slash commands in OpenClaw chat
40
+ ### 3) Use slash commands in OpenClaw chat
49
41
 
50
- - `/mnemospark wallet` → wallet status; `/mnemospark wallet help` → commands
42
+ - `/mnemospark wallet` → wallet status; `/mnemospark wallet help` → commands; `/mnemospark wallet create` → new key (backs up existing default `wallet.key` if present)
51
43
  - `/mnemospark cloud help` → storage command guide
52
44
 
53
45
  ---
@@ -85,6 +77,7 @@ Have ChatGPT or your favorite LLM evaluate the mnemospark codebase. Here's a [st
85
77
 
86
78
  - `/mnemospark wallet` — address, balance, and key file path
87
79
  - `/mnemospark wallet help` — command list and funding link
80
+ - `/mnemospark wallet create` — create a new wallet (and backup an existing default key file)
88
81
  - `/mnemospark wallet export` — export private key for backup (sensitive)
89
82
 
90
83
  ---
package/dist/cli.js CHANGED
@@ -2912,7 +2912,8 @@ async function startProxy(options) {
2912
2912
  }
2913
2913
 
2914
2914
  // src/auth.ts
2915
- import { writeFile as writeFile2, readFile as readFile2, mkdir as mkdir3 } from "fs/promises";
2915
+ import { existsSync, readFileSync } from "fs";
2916
+ import { copyFile, writeFile as writeFile2, readFile as readFile2, mkdir as mkdir3 } from "fs/promises";
2916
2917
  import { join as join5 } from "path";
2917
2918
  import { homedir as homedir4 } from "os";
2918
2919
  import { generatePrivateKey, privateKeyToAccount as privateKeyToAccount4 } from "viem/accounts";
@@ -2927,6 +2928,32 @@ var LEGACY_WALLET_DIR = join5(homedir4(), ".openclaw", "blockrun");
2927
2928
  var LEGACY_WALLET_FILE = join5(LEGACY_WALLET_DIR, "wallet.key");
2928
2929
  var WALLET_DIR = join5(homedir4(), ".openclaw", "mnemospark", "wallet");
2929
2930
  var WALLET_FILE = join5(WALLET_DIR, "wallet.key");
2931
+ function resolveWalletKeyForSlashCommandsSync() {
2932
+ const envKey = process.env.MNEMOSPARK_WALLET_KEY?.trim();
2933
+ if (isValidWalletPrivateKey(envKey)) {
2934
+ const account = privateKeyToAccount4(envKey);
2935
+ return {
2936
+ walletKey: envKey,
2937
+ address: account.address,
2938
+ keyPathLabel: "MNEMOSPARK_WALLET_KEY (environment variable)"
2939
+ };
2940
+ }
2941
+ for (const path of [WALLET_FILE, LEGACY_WALLET_FILE]) {
2942
+ try {
2943
+ if (!existsSync(path)) {
2944
+ continue;
2945
+ }
2946
+ const raw = readFileSync(path, "utf-8").trim();
2947
+ if (!isValidWalletPrivateKey(raw)) {
2948
+ continue;
2949
+ }
2950
+ const account = privateKeyToAccount4(raw);
2951
+ return { walletKey: raw, address: account.address, keyPathLabel: path };
2952
+ } catch {
2953
+ }
2954
+ }
2955
+ return null;
2956
+ }
2930
2957
  async function loadSavedWallet() {
2931
2958
  for (const path of [WALLET_FILE, LEGACY_WALLET_FILE]) {
2932
2959
  try {
@@ -2964,6 +2991,33 @@ async function generateAndSaveWallet() {
2964
2991
  }
2965
2992
  return { key, address: account.address };
2966
2993
  }
2994
+ function pickUniqueWalletKeyBackupPath(walletKeyPath) {
2995
+ const d = /* @__PURE__ */ new Date();
2996
+ const y = d.getFullYear();
2997
+ const m = String(d.getMonth() + 1).padStart(2, "0");
2998
+ const day = String(d.getDate()).padStart(2, "0");
2999
+ const base2 = `${walletKeyPath}.bak-${y}-${m}-${day}`;
3000
+ if (!existsSync(base2)) {
3001
+ return base2;
3002
+ }
3003
+ let n = 2;
3004
+ for (; ; ) {
3005
+ const candidate = `${base2}-${n}`;
3006
+ if (!existsSync(candidate)) {
3007
+ return candidate;
3008
+ }
3009
+ n += 1;
3010
+ }
3011
+ }
3012
+ async function createMnemosparkWalletWithOptionalBackup() {
3013
+ let backupPath;
3014
+ if (existsSync(WALLET_FILE)) {
3015
+ backupPath = pickUniqueWalletKeyBackupPath(WALLET_FILE);
3016
+ await copyFile(WALLET_FILE, backupPath);
3017
+ }
3018
+ const { key, address } = await generateAndSaveWallet();
3019
+ return { backupPath, key, address };
3020
+ }
2967
3021
  async function resolveOrGenerateWalletKey() {
2968
3022
  const envKey = process.env.MNEMOSPARK_WALLET_KEY?.trim();
2969
3023
  if (isValidWalletPrivateKey(envKey)) {
@@ -2990,10 +3044,6 @@ var pkg = require2(join6(__dirname, "..", "package.json"));
2990
3044
  var VERSION = pkg.version;
2991
3045
  var USER_AGENT = `mnemospark/${VERSION}`;
2992
3046
 
2993
- // src/mnemospark-handler.ts
2994
- import { existsSync, readFileSync } from "fs";
2995
- import { privateKeyToAccount as privateKeyToAccount6 } from "viem/accounts";
2996
-
2997
3047
  // src/cloud-help-onboarding.ts
2998
3048
  var CLOUD_ONBOARDING_BLOCK_LINES = [
2999
3049
  "",
@@ -3211,6 +3261,20 @@ function renderHeader(w) {
3211
3261
  HDR_FILE_OR_KEY
3212
3262
  ].join(" ");
3213
3263
  }
3264
+ function formatLsCommandCopyBlock(commandLine) {
3265
+ return ["```", commandLine, "```"].join("\n");
3266
+ }
3267
+ function formatLsWhatsNextFooter(walletAddress) {
3268
+ const downloadLine = `/mnemospark cloud download wallet-address:${walletAddress} [object-key:<object-key> | name:<friendly-name>] [latest:true|at:<timestamp>] [async:true] [orchestrator:<inline|subagent>] [timeout-seconds:<n>]`;
3269
+ const deleteLine = `/mnemospark cloud delete wallet-address:${walletAddress} [object-key:<object-key> | name:<friendly-name>] [latest:true|at:<timestamp>]`;
3270
+ return [
3271
+ "What's next? Would you like to download or delete a file:",
3272
+ "",
3273
+ formatLsCommandCopyBlock(downloadLine),
3274
+ "",
3275
+ formatLsCommandCopyBlock(deleteLine)
3276
+ ].join("\n");
3277
+ }
3214
3278
  async function buildMnemosparkLsMessage(result, ctx) {
3215
3279
  const now = ctx.now ?? /* @__PURE__ */ new Date();
3216
3280
  if (isStorageLsListResponse(result)) {
@@ -3227,7 +3291,9 @@ async function buildMnemosparkLsMessage(result, ctx) {
3227
3291
  const fence2 = ["```", [header2, ...bodyLines].join("\n"), "```"].join("\n");
3228
3292
  return `${prose2}
3229
3293
 
3230
- ${fence2}`;
3294
+ ${fence2}
3295
+
3296
+ ${formatLsWhatsNextFooter(ctx.walletAddress)}`;
3231
3297
  }
3232
3298
  const friendly = await ctx.datastore.findLatestFriendlyNameForObjectKey(
3233
3299
  ctx.walletAddress,
@@ -3264,7 +3330,9 @@ ${fence2}`;
3264
3330
  const fence = ["```", [header, line].join("\n"), "```"].join("\n");
3265
3331
  return `${prose}
3266
3332
 
3267
- ${fence}`;
3333
+ ${fence}
3334
+
3335
+ ${formatLsWhatsNextFooter(ctx.walletAddress)}`;
3268
3336
  }
3269
3337
 
3270
3338
  // src/cloud-datastore.ts
@@ -4129,7 +4197,8 @@ function routeMnemosparkArgs(args) {
4129
4197
  "\u2022 `/mnemospark help` \u2014 overview",
4130
4198
  "\u2022 `/mnemospark cloud help` \u2014 cloud commands",
4131
4199
  "\u2022 `/mnemospark wallet` \u2014 wallet status",
4132
- "\u2022 `/mnemospark wallet help` \u2014 wallet commands"
4200
+ "\u2022 `/mnemospark wallet help` \u2014 wallet commands",
4201
+ "\u2022 `/mnemospark wallet create` \u2014 new wallet (backs up existing default key)"
4133
4202
  ].join("\n")
4134
4203
  };
4135
4204
  }
@@ -7589,6 +7658,7 @@ var MNEMOSPARK_ROOT_HELP_TEXT = [
7589
7658
  "**Wallet status and funding link:**",
7590
7659
  "\u2022 `/mnemospark wallet`",
7591
7660
  "\u2022 `/mnemospark wallet help`",
7661
+ "\u2022 `/mnemospark wallet create`",
7592
7662
  "",
7593
7663
  "**Let your agent run mnemospark for you:**",
7594
7664
  "",
@@ -7602,6 +7672,7 @@ var MNEMOSPARK_WALLET_HELP_TEXT = (address) => [
7602
7672
  "**Commands:**",
7603
7673
  "\u2022 `/mnemospark wallet` \u2014 Show address, balance, and key file path",
7604
7674
  "\u2022 `/mnemospark wallet help` \u2014 This message",
7675
+ "\u2022 `/mnemospark wallet create` \u2014 Create a new wallet (and backup an existing wallet)",
7605
7676
  "\u2022 `/mnemospark wallet export` \u2014 Export private key for backup (sensitive)",
7606
7677
  "",
7607
7678
  `**Fund with USDC on Base:** https://basescan.org/address/${address}`
@@ -7611,26 +7682,7 @@ function getDefaultCloudCommandHandler() {
7611
7682
  defaultCloudCommandHandler ??= createCloudCommand().handler;
7612
7683
  return defaultCloudCommandHandler;
7613
7684
  }
7614
- var NO_WALLET_FOUND_TEXT = "No mnemospark wallet found. Run `openclaw plugins install mnemospark`.";
7615
- function resolveWalletFileSync() {
7616
- try {
7617
- if (!existsSync(WALLET_FILE)) {
7618
- return null;
7619
- }
7620
- const walletKey = readFileSync(WALLET_FILE, "utf-8").trim();
7621
- if (!walletKey.startsWith("0x") || walletKey.length !== 66) {
7622
- return null;
7623
- }
7624
- const account = privateKeyToAccount6(walletKey);
7625
- const address = account.address.replace(/\s/g, "");
7626
- if (!address) {
7627
- return null;
7628
- }
7629
- return { walletKey, address };
7630
- } catch {
7631
- return null;
7632
- }
7633
- }
7685
+ var NO_WALLET_FOUND_TEXT = "No mnemospark wallet found. Run `openclaw plugins install mnemospark` or set MNEMOSPARK_WALLET_KEY.";
7634
7686
  async function runMnemosparkSlashHandler(ctx, options) {
7635
7687
  const route = routeMnemosparkArgs(ctx.args);
7636
7688
  if (route.kind === "root-help") {
@@ -7676,6 +7728,15 @@ async function handleWalletSlash(rest) {
7676
7728
  }
7677
7729
  return buildWalletExportResponse();
7678
7730
  }
7731
+ if (parsed.name === "create") {
7732
+ if (afterFirst.trim()) {
7733
+ return {
7734
+ text: "Unexpected extra arguments after `create`. Use `/mnemospark wallet create` alone.",
7735
+ isError: true
7736
+ };
7737
+ }
7738
+ return buildWalletCreateResponse();
7739
+ }
7679
7740
  if (parsed.name === "status") {
7680
7741
  return buildWalletStatusResponse();
7681
7742
  }
@@ -7684,15 +7745,15 @@ async function handleWalletSlash(rest) {
7684
7745
  isError: true
7685
7746
  };
7686
7747
  }
7687
- async function buildWalletStatusResponse() {
7688
- const wallet = resolveWalletFileSync();
7748
+ async function buildWalletStatusResponse(walletOverride) {
7749
+ const wallet = walletOverride ?? resolveWalletKeyForSlashCommandsSync();
7689
7750
  if (!wallet) {
7690
7751
  return {
7691
7752
  text: NO_WALLET_FOUND_TEXT,
7692
7753
  isError: true
7693
7754
  };
7694
7755
  }
7695
- const { address } = wallet;
7756
+ const { address, keyPathLabel } = wallet;
7696
7757
  let balanceText = "Balance: (checking...)";
7697
7758
  try {
7698
7759
  const monitor = new BalanceMonitor(address);
@@ -7707,19 +7768,47 @@ async function buildWalletStatusResponse() {
7707
7768
  "",
7708
7769
  `**Address:** \`${address}\``,
7709
7770
  `**${balanceText}**`,
7710
- `**Key File:** \`${WALLET_FILE}\``,
7771
+ `**Key File:** \`${keyPathLabel}\``,
7711
7772
  "",
7712
7773
  "**Commands:**",
7713
7774
  "\u2022 `/mnemospark wallet` \u2014 Show this status",
7714
7775
  "\u2022 `/mnemospark wallet help` \u2014 Commands and funding link",
7776
+ "\u2022 `/mnemospark wallet create` \u2014 Create a new wallet (and backup an existing wallet)",
7715
7777
  "\u2022 `/mnemospark wallet export` \u2014 Export private key for backup",
7716
7778
  "",
7717
7779
  `**Fund with USDC on Base:** https://basescan.org/address/${address}`
7718
7780
  ].join("\n")
7719
7781
  };
7720
7782
  }
7783
+ async function buildWalletCreateResponse() {
7784
+ let backupPath;
7785
+ let createdAddress = "";
7786
+ try {
7787
+ ({ backupPath, address: createdAddress } = await createMnemosparkWalletWithOptionalBackup());
7788
+ } catch (err) {
7789
+ return {
7790
+ text: `Failed to create wallet: ${err instanceof Error ? err.message : String(err)}`,
7791
+ isError: true
7792
+ };
7793
+ }
7794
+ const statusResponse = await buildWalletStatusResponse({
7795
+ address: createdAddress,
7796
+ keyPathLabel: WALLET_FILE
7797
+ });
7798
+ if (statusResponse.isError) {
7799
+ return statusResponse;
7800
+ }
7801
+ const createMessageLines = backupPath ? [
7802
+ "\u2705 Existing wallet key was backed up before creating the new wallet.",
7803
+ `**Backup File:** \`${backupPath}\``
7804
+ ] : ["\u2705 New wallet created."];
7805
+ return {
7806
+ ...statusResponse,
7807
+ text: [...createMessageLines, "", statusResponse.text ?? ""].join("\n")
7808
+ };
7809
+ }
7721
7810
  async function buildWalletHelpResponse() {
7722
- const wallet = resolveWalletFileSync();
7811
+ const wallet = resolveWalletKeyForSlashCommandsSync();
7723
7812
  if (!wallet) {
7724
7813
  return {
7725
7814
  text: NO_WALLET_FOUND_TEXT,
@@ -7730,7 +7819,7 @@ async function buildWalletHelpResponse() {
7730
7819
  return { text: MNEMOSPARK_WALLET_HELP_TEXT(address) };
7731
7820
  }
7732
7821
  async function buildWalletExportResponse() {
7733
- const wallet = resolveWalletFileSync();
7822
+ const wallet = resolveWalletKeyForSlashCommandsSync();
7734
7823
  if (!wallet) {
7735
7824
  return {
7736
7825
  text: NO_WALLET_FOUND_TEXT,