mnemospark 1.5.1 → 2026.4.6

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,17 @@ 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
34
+ By default the plugin uses the production mnemospark API at **https://api.mnemospark.ai**. Set **`MNEMOSPARK_BACKEND_API_BASE_URL`** only when you need a different endpoint (for example staging or a private API URL).
35
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
36
+ ### 2) Restart gateway after updates
43
37
 
44
38
  ```bash
45
39
  openclaw gateway restart
46
40
  ```
47
41
 
48
- ### 4) Use slash commands in OpenClaw chat
42
+ ### 3) Use slash commands in OpenClaw chat
49
43
 
50
- - `/mnemospark wallet` → wallet status; `/mnemospark wallet help` → commands
44
+ - `/mnemospark wallet` → wallet status; `/mnemospark wallet help` → commands; `/mnemospark wallet create` → new key (backs up existing default `wallet.key` if present)
51
45
  - `/mnemospark cloud help` → storage command guide
52
46
 
53
47
  ---
@@ -85,6 +79,7 @@ Have ChatGPT or your favorite LLM evaluate the mnemospark codebase. Here's a [st
85
79
 
86
80
  - `/mnemospark wallet` — address, balance, and key file path
87
81
  - `/mnemospark wallet help` — command list and funding link
82
+ - `/mnemospark wallet create` — create a new wallet (and backup an existing default key file)
88
83
  - `/mnemospark wallet export` — export private key for backup (sensitive)
89
84
 
90
85
  ---
@@ -155,20 +150,20 @@ The blockchain transaction is the payment record.
155
150
 
156
151
  Optional unless noted. All names use the `MNEMOSPARK_` prefix.
157
152
 
158
- | Variable | Purpose |
159
- | ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
160
- | `MNEMOSPARK_BACKEND_API_BASE_URL` | Base URL for the mnemospark backend API (required for the local HTTP proxy to forward storage calls). Example: `https://{api-id}.execute-api.{region}.amazonaws.com/{stage}`. |
161
- | `MNEMOSPARK_PROXY_PORT` | TCP port for the mnemospark HTTP proxy (default `7120`). |
162
- | `MNEMOSPARK_DOWNLOAD_DIR` | Directory where the proxy writes downloaded objects (default `~/.openclaw/mnemospark/downloads/`). |
163
- | `MNEMOSPARK_WALLET_KEY` | Path to the wallet private key file when not using the default `~/.openclaw/mnemospark/wallet/wallet.key`. |
164
- | `MNEMOSPARK_REMOVE_BACKUP_FILE` | After a **successful** cloud upload, delete the local backup archive under `~/.openclaw/mnemospark/backup/`. **Default when unset:** remove the file. Set to `0`, `false`, `no`, or `n` to keep it; `1`, `true`, `yes`, or `y` to remove. |
165
- | `MNEMOSPARK_DISABLED` | Set to `true` or `1` to disable plugin registration. |
166
- | `MNEMOSPARK_DISABLE_SQLITE` | Set to `1` to disable local SQLite (`state.db`); cloud commands that need local state will fail. |
167
- | `MNEMOSPARK_SQLITE_STRICT` | Set to `1` so certain SQLite consistency checks (e.g. friendly-name verification after upload) throw instead of warning. |
168
- | `MNEMOSPARK_PROXY_VERBOSE_404` | When `1`, `true`, or `yes`, the local HTTP proxy includes a `message` field on **404** responses describing supported paths. Default (unset) is a generic JSON body `{ "error": "Not found" }` only (reduces reconnaissance). |
169
- | `MNEMOSPARK_CRON_AGENT_ID` | OpenClaw agent id used for the monthly renewal cron (default `mnemospark-renewal`). |
170
- | `MNEMOSPARK_CRON_NODE_BIN` | Absolute path to `node` for renewal cron exec (default `/usr/bin/node`). |
171
- | `MNEMOSPARK_DISABLE_OPENCLAW_PREREQ` | Set to `1` to skip automatic runbook application everywhere it runs (plugin load, CLI install/update; for advanced debugging only). |
153
+ | Variable | Purpose |
154
+ | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
155
+ | `MNEMOSPARK_BACKEND_API_BASE_URL` | Base URL for the mnemospark backend API (required for the local HTTP proxy to forward storage calls). **Default:** `https://api.mnemospark.ai` (production). Set this variable only to override—for example staging or a custom API Gateway URL. |
156
+ | `MNEMOSPARK_PROXY_PORT` | TCP port for the mnemospark HTTP proxy (default `7120`). |
157
+ | `MNEMOSPARK_DOWNLOAD_DIR` | Directory where the proxy writes downloaded objects (default `~/.openclaw/mnemospark/downloads/`). |
158
+ | `MNEMOSPARK_WALLET_KEY` | Path to the wallet private key file when not using the default `~/.openclaw/mnemospark/wallet/wallet.key`. |
159
+ | `MNEMOSPARK_REMOVE_BACKUP_FILE` | After a **successful** cloud upload, delete the local backup archive under `~/.openclaw/mnemospark/backup/`. **Default when unset:** remove the file. Set to `0`, `false`, `no`, or `n` to keep it; `1`, `true`, `yes`, or `y` to remove. |
160
+ | `MNEMOSPARK_DISABLED` | Set to `true` or `1` to disable plugin registration. |
161
+ | `MNEMOSPARK_DISABLE_SQLITE` | Set to `1` to disable local SQLite (`state.db`); cloud commands that need local state will fail. |
162
+ | `MNEMOSPARK_SQLITE_STRICT` | Set to `1` so certain SQLite consistency checks (e.g. friendly-name verification after upload) throw instead of warning. |
163
+ | `MNEMOSPARK_PROXY_VERBOSE_404` | When `1`, `true`, or `yes`, the local HTTP proxy includes a `message` field on **404** responses describing supported paths. Default (unset) is a generic JSON body `{ "error": "Not found" }` only (reduces reconnaissance). |
164
+ | `MNEMOSPARK_CRON_AGENT_ID` | OpenClaw agent id used for the monthly renewal cron (default `mnemospark-renewal`). |
165
+ | `MNEMOSPARK_CRON_NODE_BIN` | Absolute path to `node` for renewal cron exec (default `/usr/bin/node`). |
166
+ | `MNEMOSPARK_DISABLE_OPENCLAW_PREREQ` | Set to `1` to skip automatic runbook application everywhere it runs (plugin load, CLI install/update; for advanced debugging only). |
172
167
 
173
168
  ---
174
169
 
package/dist/cli.js CHANGED
@@ -146,6 +146,7 @@ var BalanceMonitor = class {
146
146
 
147
147
  // src/config.ts
148
148
  var DEFAULT_PORT = 7120;
149
+ var DEFAULT_BACKEND_API_BASE_URL = "https://api.mnemospark.ai";
149
150
  var PROXY_PORT = (() => {
150
151
  const envPort = process.env.MNEMOSPARK_PROXY_PORT;
151
152
  if (envPort) {
@@ -156,7 +157,7 @@ var PROXY_PORT = (() => {
156
157
  }
157
158
  return DEFAULT_PORT;
158
159
  })();
159
- var MNEMOSPARK_BACKEND_API_BASE_URL = (process.env.MNEMOSPARK_BACKEND_API_BASE_URL ?? "").trim();
160
+ var MNEMOSPARK_BACKEND_API_BASE_URL = (process.env.MNEMOSPARK_BACKEND_API_BASE_URL || DEFAULT_BACKEND_API_BASE_URL).trim();
160
161
  var MNEMOSPARK_PROXY_VERBOSE_404 = (() => {
161
162
  const v = process.env.MNEMOSPARK_PROXY_VERBOSE_404?.trim().toLowerCase();
162
163
  return v === "1" || v === "true" || v === "yes";
@@ -2912,7 +2913,8 @@ async function startProxy(options) {
2912
2913
  }
2913
2914
 
2914
2915
  // src/auth.ts
2915
- import { writeFile as writeFile2, readFile as readFile2, mkdir as mkdir3 } from "fs/promises";
2916
+ import { existsSync, readFileSync } from "fs";
2917
+ import { copyFile, writeFile as writeFile2, readFile as readFile2, mkdir as mkdir3 } from "fs/promises";
2916
2918
  import { join as join5 } from "path";
2917
2919
  import { homedir as homedir4 } from "os";
2918
2920
  import { generatePrivateKey, privateKeyToAccount as privateKeyToAccount4 } from "viem/accounts";
@@ -2927,6 +2929,32 @@ var LEGACY_WALLET_DIR = join5(homedir4(), ".openclaw", "blockrun");
2927
2929
  var LEGACY_WALLET_FILE = join5(LEGACY_WALLET_DIR, "wallet.key");
2928
2930
  var WALLET_DIR = join5(homedir4(), ".openclaw", "mnemospark", "wallet");
2929
2931
  var WALLET_FILE = join5(WALLET_DIR, "wallet.key");
2932
+ function resolveWalletKeyForSlashCommandsSync() {
2933
+ const envKey = process.env.MNEMOSPARK_WALLET_KEY?.trim();
2934
+ if (isValidWalletPrivateKey(envKey)) {
2935
+ const account = privateKeyToAccount4(envKey);
2936
+ return {
2937
+ walletKey: envKey,
2938
+ address: account.address,
2939
+ keyPathLabel: "MNEMOSPARK_WALLET_KEY (environment variable)"
2940
+ };
2941
+ }
2942
+ for (const path of [WALLET_FILE, LEGACY_WALLET_FILE]) {
2943
+ try {
2944
+ if (!existsSync(path)) {
2945
+ continue;
2946
+ }
2947
+ const raw = readFileSync(path, "utf-8").trim();
2948
+ if (!isValidWalletPrivateKey(raw)) {
2949
+ continue;
2950
+ }
2951
+ const account = privateKeyToAccount4(raw);
2952
+ return { walletKey: raw, address: account.address, keyPathLabel: path };
2953
+ } catch {
2954
+ }
2955
+ }
2956
+ return null;
2957
+ }
2930
2958
  async function loadSavedWallet() {
2931
2959
  for (const path of [WALLET_FILE, LEGACY_WALLET_FILE]) {
2932
2960
  try {
@@ -2964,6 +2992,33 @@ async function generateAndSaveWallet() {
2964
2992
  }
2965
2993
  return { key, address: account.address };
2966
2994
  }
2995
+ function pickUniqueWalletKeyBackupPath(walletKeyPath) {
2996
+ const d = /* @__PURE__ */ new Date();
2997
+ const y = d.getFullYear();
2998
+ const m = String(d.getMonth() + 1).padStart(2, "0");
2999
+ const day = String(d.getDate()).padStart(2, "0");
3000
+ const base2 = `${walletKeyPath}.bak-${y}-${m}-${day}`;
3001
+ if (!existsSync(base2)) {
3002
+ return base2;
3003
+ }
3004
+ let n = 2;
3005
+ for (; ; ) {
3006
+ const candidate = `${base2}-${n}`;
3007
+ if (!existsSync(candidate)) {
3008
+ return candidate;
3009
+ }
3010
+ n += 1;
3011
+ }
3012
+ }
3013
+ async function createMnemosparkWalletWithOptionalBackup() {
3014
+ let backupPath;
3015
+ if (existsSync(WALLET_FILE)) {
3016
+ backupPath = pickUniqueWalletKeyBackupPath(WALLET_FILE);
3017
+ await copyFile(WALLET_FILE, backupPath);
3018
+ }
3019
+ const { key, address } = await generateAndSaveWallet();
3020
+ return { backupPath, key, address };
3021
+ }
2967
3022
  async function resolveOrGenerateWalletKey() {
2968
3023
  const envKey = process.env.MNEMOSPARK_WALLET_KEY?.trim();
2969
3024
  if (isValidWalletPrivateKey(envKey)) {
@@ -2990,10 +3045,6 @@ var pkg = require2(join6(__dirname, "..", "package.json"));
2990
3045
  var VERSION = pkg.version;
2991
3046
  var USER_AGENT = `mnemospark/${VERSION}`;
2992
3047
 
2993
- // src/mnemospark-handler.ts
2994
- import { existsSync, readFileSync } from "fs";
2995
- import { privateKeyToAccount as privateKeyToAccount6 } from "viem/accounts";
2996
-
2997
3048
  // src/cloud-help-onboarding.ts
2998
3049
  var CLOUD_ONBOARDING_BLOCK_LINES = [
2999
3050
  "",
@@ -4147,7 +4198,8 @@ function routeMnemosparkArgs(args) {
4147
4198
  "\u2022 `/mnemospark help` \u2014 overview",
4148
4199
  "\u2022 `/mnemospark cloud help` \u2014 cloud commands",
4149
4200
  "\u2022 `/mnemospark wallet` \u2014 wallet status",
4150
- "\u2022 `/mnemospark wallet help` \u2014 wallet commands"
4201
+ "\u2022 `/mnemospark wallet help` \u2014 wallet commands",
4202
+ "\u2022 `/mnemospark wallet create` \u2014 new wallet (backs up existing default key)"
4151
4203
  ].join("\n")
4152
4204
  };
4153
4205
  }
@@ -7607,6 +7659,7 @@ var MNEMOSPARK_ROOT_HELP_TEXT = [
7607
7659
  "**Wallet status and funding link:**",
7608
7660
  "\u2022 `/mnemospark wallet`",
7609
7661
  "\u2022 `/mnemospark wallet help`",
7662
+ "\u2022 `/mnemospark wallet create`",
7610
7663
  "",
7611
7664
  "**Let your agent run mnemospark for you:**",
7612
7665
  "",
@@ -7620,6 +7673,7 @@ var MNEMOSPARK_WALLET_HELP_TEXT = (address) => [
7620
7673
  "**Commands:**",
7621
7674
  "\u2022 `/mnemospark wallet` \u2014 Show address, balance, and key file path",
7622
7675
  "\u2022 `/mnemospark wallet help` \u2014 This message",
7676
+ "\u2022 `/mnemospark wallet create` \u2014 Create a new wallet (and backup an existing wallet)",
7623
7677
  "\u2022 `/mnemospark wallet export` \u2014 Export private key for backup (sensitive)",
7624
7678
  "",
7625
7679
  `**Fund with USDC on Base:** https://basescan.org/address/${address}`
@@ -7629,26 +7683,7 @@ function getDefaultCloudCommandHandler() {
7629
7683
  defaultCloudCommandHandler ??= createCloudCommand().handler;
7630
7684
  return defaultCloudCommandHandler;
7631
7685
  }
7632
- var NO_WALLET_FOUND_TEXT = "No mnemospark wallet found. Run `openclaw plugins install mnemospark`.";
7633
- function resolveWalletFileSync() {
7634
- try {
7635
- if (!existsSync(WALLET_FILE)) {
7636
- return null;
7637
- }
7638
- const walletKey = readFileSync(WALLET_FILE, "utf-8").trim();
7639
- if (!walletKey.startsWith("0x") || walletKey.length !== 66) {
7640
- return null;
7641
- }
7642
- const account = privateKeyToAccount6(walletKey);
7643
- const address = account.address.replace(/\s/g, "");
7644
- if (!address) {
7645
- return null;
7646
- }
7647
- return { walletKey, address };
7648
- } catch {
7649
- return null;
7650
- }
7651
- }
7686
+ var NO_WALLET_FOUND_TEXT = "No mnemospark wallet found. Run `openclaw plugins install mnemospark` or set MNEMOSPARK_WALLET_KEY.";
7652
7687
  async function runMnemosparkSlashHandler(ctx, options) {
7653
7688
  const route = routeMnemosparkArgs(ctx.args);
7654
7689
  if (route.kind === "root-help") {
@@ -7694,6 +7729,15 @@ async function handleWalletSlash(rest) {
7694
7729
  }
7695
7730
  return buildWalletExportResponse();
7696
7731
  }
7732
+ if (parsed.name === "create") {
7733
+ if (afterFirst.trim()) {
7734
+ return {
7735
+ text: "Unexpected extra arguments after `create`. Use `/mnemospark wallet create` alone.",
7736
+ isError: true
7737
+ };
7738
+ }
7739
+ return buildWalletCreateResponse();
7740
+ }
7697
7741
  if (parsed.name === "status") {
7698
7742
  return buildWalletStatusResponse();
7699
7743
  }
@@ -7702,15 +7746,15 @@ async function handleWalletSlash(rest) {
7702
7746
  isError: true
7703
7747
  };
7704
7748
  }
7705
- async function buildWalletStatusResponse() {
7706
- const wallet = resolveWalletFileSync();
7749
+ async function buildWalletStatusResponse(walletOverride) {
7750
+ const wallet = walletOverride ?? resolveWalletKeyForSlashCommandsSync();
7707
7751
  if (!wallet) {
7708
7752
  return {
7709
7753
  text: NO_WALLET_FOUND_TEXT,
7710
7754
  isError: true
7711
7755
  };
7712
7756
  }
7713
- const { address } = wallet;
7757
+ const { address, keyPathLabel } = wallet;
7714
7758
  let balanceText = "Balance: (checking...)";
7715
7759
  try {
7716
7760
  const monitor = new BalanceMonitor(address);
@@ -7725,19 +7769,47 @@ async function buildWalletStatusResponse() {
7725
7769
  "",
7726
7770
  `**Address:** \`${address}\``,
7727
7771
  `**${balanceText}**`,
7728
- `**Key File:** \`${WALLET_FILE}\``,
7772
+ `**Key File:** \`${keyPathLabel}\``,
7729
7773
  "",
7730
7774
  "**Commands:**",
7731
7775
  "\u2022 `/mnemospark wallet` \u2014 Show this status",
7732
7776
  "\u2022 `/mnemospark wallet help` \u2014 Commands and funding link",
7777
+ "\u2022 `/mnemospark wallet create` \u2014 Create a new wallet (and backup an existing wallet)",
7733
7778
  "\u2022 `/mnemospark wallet export` \u2014 Export private key for backup",
7734
7779
  "",
7735
7780
  `**Fund with USDC on Base:** https://basescan.org/address/${address}`
7736
7781
  ].join("\n")
7737
7782
  };
7738
7783
  }
7784
+ async function buildWalletCreateResponse() {
7785
+ let backupPath;
7786
+ let createdAddress = "";
7787
+ try {
7788
+ ({ backupPath, address: createdAddress } = await createMnemosparkWalletWithOptionalBackup());
7789
+ } catch (err) {
7790
+ return {
7791
+ text: `Failed to create wallet: ${err instanceof Error ? err.message : String(err)}`,
7792
+ isError: true
7793
+ };
7794
+ }
7795
+ const statusResponse = await buildWalletStatusResponse({
7796
+ address: createdAddress,
7797
+ keyPathLabel: WALLET_FILE
7798
+ });
7799
+ if (statusResponse.isError) {
7800
+ return statusResponse;
7801
+ }
7802
+ const createMessageLines = backupPath ? [
7803
+ "\u2705 Existing wallet key was backed up before creating the new wallet.",
7804
+ `**Backup File:** \`${backupPath}\``
7805
+ ] : ["\u2705 New wallet created."];
7806
+ return {
7807
+ ...statusResponse,
7808
+ text: [...createMessageLines, "", statusResponse.text ?? ""].join("\n")
7809
+ };
7810
+ }
7739
7811
  async function buildWalletHelpResponse() {
7740
- const wallet = resolveWalletFileSync();
7812
+ const wallet = resolveWalletKeyForSlashCommandsSync();
7741
7813
  if (!wallet) {
7742
7814
  return {
7743
7815
  text: NO_WALLET_FOUND_TEXT,
@@ -7748,7 +7820,7 @@ async function buildWalletHelpResponse() {
7748
7820
  return { text: MNEMOSPARK_WALLET_HELP_TEXT(address) };
7749
7821
  }
7750
7822
  async function buildWalletExportResponse() {
7751
- const wallet = resolveWalletFileSync();
7823
+ const wallet = resolveWalletKeyForSlashCommandsSync();
7752
7824
  if (!wallet) {
7753
7825
  return {
7754
7826
  text: NO_WALLET_FOUND_TEXT,