mnemospark 1.2.0 β 1.2.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/README.md +48 -12
- package/dist/cli.js +135 -41
- package/dist/cli.js.map +1 -1
- package/dist/index.js +135 -41
- package/dist/index.js.map +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/skills/mnemospark/SKILL.md +4 -2
- package/skills/mnemospark/references/commands.md +1 -1
- package/scripts/README.md +0 -55
- package/scripts/install-aws-cli.sh +0 -28
- package/scripts/install-jq.sh +0 -13
- package/scripts/install-pnpm.sh +0 -20
- package/scripts/reinstall.sh +0 -102
- package/scripts/uninstall.sh +0 -67
- package/scripts/verify-dev-tools.sh +0 -56
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
**Wallet and go. π**
|
|
4
4
|
_No forms. No email. Just Base. π_
|
|
5
5
|
|
|
6
|
-
mnemospark is an agentic service layer for OpenClaw
|
|
6
|
+
mnemospark is an agentic service layer for OpenClaw plus a standalone x402 payment + verification backend. It enables encrypted, authenticated, fully autonomous cloud and data workflowsβpaid via x402 with USDC on Base. No human onboarding. No API keys. The blockchain transaction is the record.
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
@@ -11,7 +11,7 @@ mnemospark is an agentic service layer for OpenClaw and a standalone x402 paymen
|
|
|
11
11
|
|
|
12
12
|
mnemospark connects OpenClaw agents to cloud workflows with wallet-native auth + payment rails.
|
|
13
13
|
|
|
14
|
-
- **Wallet-
|
|
14
|
+
- **Wallet-native authentication** for storage/API actions
|
|
15
15
|
- **x402-native payments** with USDC on Base
|
|
16
16
|
- **Agent-first flow** (quote β pay β provision)
|
|
17
17
|
- **Encrypted payload support** and structured request signing
|
|
@@ -24,7 +24,7 @@ mnemospark connects OpenClaw agents to cloud workflows with wallet-native auth +
|
|
|
24
24
|
### 1) Install the plugin in OpenClaw
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
|
-
openclaw plugins install mnemospark
|
|
27
|
+
openclaw plugins install mnemospark --dangerously-force-unsafe-install
|
|
28
28
|
openclaw gateway start
|
|
29
29
|
```
|
|
30
30
|
|
|
@@ -52,40 +52,63 @@ openclaw gateway restart
|
|
|
52
52
|
|
|
53
53
|
---
|
|
54
54
|
|
|
55
|
+
## Slash command reference
|
|
56
|
+
|
|
57
|
+
**Syntax**
|
|
58
|
+
|
|
59
|
+
- **Chat / OpenClaw (primary):** use `key:value` for arguments (for example `wallet-address:0xβ¦`, `region:us-east-1`). `key=value` is also accepted.
|
|
60
|
+
- **Agent-driven workflows and CLI-style usage:** prefer `--parameter value` (for example `npx mnemospark` or shell scripts).
|
|
61
|
+
|
|
62
|
+
**Top-level routes** (after `/mnemospark`)
|
|
63
|
+
|
|
64
|
+
- `/mnemospark` or `/mnemospark help` β overview
|
|
65
|
+
- `/mnemospark cloud β¦` β cloud storage (see below)
|
|
66
|
+
- `/mnemospark wallet β¦` β wallet helpers
|
|
67
|
+
|
|
68
|
+
**`/mnemospark cloud`** β includes: `cloud` / `cloud help`, `backup`, `price-storage`, `upload`, `payment-settle`, `ls`, `download`, `delete`, `op-status`. Optional flags include `async:true`, `orchestrator:inline|subagent`, `timeout-seconds:<n>`. For the full cloud guide, run `/mnemospark cloud help` in chat.
|
|
69
|
+
|
|
70
|
+
**`/mnemospark wallet`**
|
|
71
|
+
|
|
72
|
+
- `/mnemospark wallet` β address, balance, and key file path
|
|
73
|
+
- `/mnemospark wallet help` β command list and funding link
|
|
74
|
+
- `/mnemospark wallet export` β export private key for backup (sensitive)
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
55
78
|
## Core Commands
|
|
56
79
|
|
|
57
|
-
Use via `/mnemospark cloud β¦` (or `/mnemospark wallet β¦`) in OpenClaw chat.
|
|
80
|
+
Use via `/mnemospark cloud β¦` (or `/mnemospark wallet β¦`) in OpenClaw chat. Prefer `key:value` in chat; use `--wallet-address` style for scripted or agent-driven flows.
|
|
58
81
|
|
|
59
82
|
### Get a storage quote
|
|
60
83
|
|
|
61
84
|
```text
|
|
62
|
-
/mnemospark cloud price-storage
|
|
85
|
+
/mnemospark cloud price-storage wallet-address:<addr> object-id:<id> object-id-hash:<sha256> gb:<gb> provider:aws region:us-east-1
|
|
63
86
|
```
|
|
64
87
|
|
|
65
|
-
Use other regions by changing
|
|
88
|
+
Use other regions by changing `provider:` and `region:` (defaults: `aws` / `us-east-1`).
|
|
66
89
|
|
|
67
90
|
### Upload using quote
|
|
68
91
|
|
|
69
92
|
```text
|
|
70
|
-
/mnemospark cloud upload
|
|
93
|
+
/mnemospark cloud upload quote-id:<quote-id> wallet-address:<addr> object-id:<id> object-id-hash:<sha256>
|
|
71
94
|
```
|
|
72
95
|
|
|
73
96
|
### List objects
|
|
74
97
|
|
|
75
98
|
```text
|
|
76
|
-
/mnemospark cloud ls
|
|
99
|
+
/mnemospark cloud ls wallet-address:<addr> object-key:<object-key>
|
|
77
100
|
```
|
|
78
101
|
|
|
79
102
|
### Download object
|
|
80
103
|
|
|
81
104
|
```text
|
|
82
|
-
/mnemospark cloud download
|
|
105
|
+
/mnemospark cloud download wallet-address:<addr> object-key:<object-key>
|
|
83
106
|
```
|
|
84
107
|
|
|
85
108
|
### Delete object
|
|
86
109
|
|
|
87
110
|
```text
|
|
88
|
-
/mnemospark cloud delete
|
|
111
|
+
/mnemospark cloud delete wallet-address:<addr> object-key:<object-key>
|
|
89
112
|
```
|
|
90
113
|
|
|
91
114
|
---
|
|
@@ -95,7 +118,7 @@ Use other regions by changing `--provider` and `--region` (defaults: `aws` / `us
|
|
|
95
118
|
mnemospark follows a quote-and-pay execution model:
|
|
96
119
|
|
|
97
120
|
1. Agent requests a quote.
|
|
98
|
-
2. Agent provides wallet-
|
|
121
|
+
2. Agent provides wallet-native + payment authorization.
|
|
99
122
|
3. Backend verifies payment/auth context.
|
|
100
123
|
4. Storage action executes.
|
|
101
124
|
|
|
@@ -128,6 +151,7 @@ Optional unless noted. All names use the `MNEMOSPARK_` prefix.
|
|
|
128
151
|
| `MNEMOSPARK_DISABLED` | Set to `true` or `1` to disable plugin registration. |
|
|
129
152
|
| `MNEMOSPARK_DISABLE_SQLITE` | Set to `1` to disable local SQLite (`state.db`); cloud commands that need local state will fail. |
|
|
130
153
|
| `MNEMOSPARK_SQLITE_STRICT` | Set to `1` so certain SQLite consistency checks (e.g. friendly-name verification after upload) throw instead of warning. |
|
|
154
|
+
| `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). |
|
|
131
155
|
|
|
132
156
|
---
|
|
133
157
|
|
|
@@ -141,11 +165,23 @@ Optional unless noted. All names use the `MNEMOSPARK_` prefix.
|
|
|
141
165
|
|
|
142
166
|
---
|
|
143
167
|
|
|
168
|
+
## OpenClaw Install Warning
|
|
169
|
+
|
|
170
|
+
If OpenClaw shows a warning about **dangerous code patterns** when installing or updating mnemosparkβoften mentioning shell execution (`child_process`), environment variables, and network accessβhere is what is going on.
|
|
171
|
+
|
|
172
|
+
mnemospark is an **OpenClaw plugin** that talks to **your configured mnemospark backend**, runs a **local HTTP proxy** for storage workflows, and can **invoke the `openclaw` CLI** and system tools when needed (for example creating archives with `tar` or running `npm` when you use the update command). Those features use the same low-level Node.js APIsβ`child_process` and `fetch`βthat security tools also associate with risky software, so the installer may warn you even when the behavior is intentional and benign.
|
|
173
|
+
|
|
174
|
+
We also read **environment variables** you set on purpose (such as `MNEMOSPARK_BACKEND_API_BASE_URL`, `MNEMOSPARK_PROXY_PORT`, or wallet-related settings) so you can configure the plugin without editing code. Automated scans sometimes flag βenvironment access + networkβ as a possible credential-stealing pattern. In mnemospark, that combination exists because the plugin is **configurable and networked by design**, not because we are harvesting your unrelated secrets.
|
|
175
|
+
|
|
176
|
+
mnemospark is **open source**. If you want extra assurance, review the repository, search for `child_process`, `process.env`, and `fetch`, and run your own tests in a safe environment. The warning helps keep the ecosystem safe; for mnemospark it reflects **capabilities**, not a finding of malicious intent.
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
144
180
|
## Troubleshooting
|
|
145
181
|
|
|
146
182
|
- **Missing wallet/auth errors**: verify wallet key is present and request signature headers are generated.
|
|
147
183
|
- **402 payment required**: expected in challenge flow; ensure client retries with payment authorization.
|
|
148
|
-
- **Upload/storage backend errors**: verify cloud permissions (e.g
|
|
184
|
+
- **Upload/storage backend errors**: verify cloud permissions (e.g. bucket access + IAM role rights).
|
|
149
185
|
- **Command not recognized**: confirm plugin installed and gateway restarted.
|
|
150
186
|
- **One-step operation correlation**: run `./skills/mnemospark/scripts/debug-operation.sh <operation-id>` (or omit ID to use latest).
|
|
151
187
|
|
package/dist/cli.js
CHANGED
|
@@ -157,6 +157,10 @@ var PROXY_PORT = (() => {
|
|
|
157
157
|
return DEFAULT_PORT;
|
|
158
158
|
})();
|
|
159
159
|
var MNEMOSPARK_BACKEND_API_BASE_URL = (process.env.MNEMOSPARK_BACKEND_API_BASE_URL ?? "").trim();
|
|
160
|
+
var MNEMOSPARK_PROXY_VERBOSE_404 = (() => {
|
|
161
|
+
const v = process.env.MNEMOSPARK_PROXY_VERBOSE_404?.trim().toLowerCase();
|
|
162
|
+
return v === "1" || v === "true" || v === "yes";
|
|
163
|
+
})();
|
|
160
164
|
|
|
161
165
|
// src/mnemospark-request-sign.ts
|
|
162
166
|
import { getAddress } from "viem";
|
|
@@ -1733,8 +1737,15 @@ async function readProxyJsonBody(req) {
|
|
|
1733
1737
|
}
|
|
1734
1738
|
return JSON.parse(bodyText);
|
|
1735
1739
|
}
|
|
1740
|
+
function createJsonResponseHeaders() {
|
|
1741
|
+
return {
|
|
1742
|
+
"Content-Type": "application/json",
|
|
1743
|
+
"X-Content-Type-Options": "nosniff",
|
|
1744
|
+
"Cache-Control": "no-store"
|
|
1745
|
+
};
|
|
1746
|
+
}
|
|
1736
1747
|
function sendJson(res, status, body) {
|
|
1737
|
-
res.writeHead(status,
|
|
1748
|
+
res.writeHead(status, createJsonResponseHeaders());
|
|
1738
1749
|
res.end(JSON.stringify(body));
|
|
1739
1750
|
}
|
|
1740
1751
|
function logProxyEvent(level, event, fields = {}) {
|
|
@@ -1794,7 +1805,9 @@ function isAlreadySettledConflict(status, bodyText) {
|
|
|
1794
1805
|
}
|
|
1795
1806
|
function createBackendForwardHeaders(response) {
|
|
1796
1807
|
const responseHeaders = {
|
|
1797
|
-
"Content-Type": response.contentType
|
|
1808
|
+
"Content-Type": response.contentType,
|
|
1809
|
+
"X-Content-Type-Options": "nosniff",
|
|
1810
|
+
"Cache-Control": "no-store"
|
|
1798
1811
|
};
|
|
1799
1812
|
if (response.paymentRequired) {
|
|
1800
1813
|
responseHeaders["PAYMENT-REQUIRED"] = response.paymentRequired;
|
|
@@ -1832,6 +1845,10 @@ function createWalletRequiredBody() {
|
|
|
1832
1845
|
message: "wallet required for storage endpoints"
|
|
1833
1846
|
});
|
|
1834
1847
|
}
|
|
1848
|
+
function sendWalletRequired(res) {
|
|
1849
|
+
res.writeHead(400, createJsonResponseHeaders());
|
|
1850
|
+
res.end(createWalletRequiredBody());
|
|
1851
|
+
}
|
|
1835
1852
|
function getProxyPort() {
|
|
1836
1853
|
return PROXY_PORT;
|
|
1837
1854
|
}
|
|
@@ -1931,6 +1948,18 @@ async function startProxy(options) {
|
|
|
1931
1948
|
}
|
|
1932
1949
|
correlation.wallet_address = requestPayload.wallet_address;
|
|
1933
1950
|
correlation.object_id = requestPayload.object_id;
|
|
1951
|
+
if (requestPayload.wallet_address.toLowerCase() !== proxyWalletAddressLower) {
|
|
1952
|
+
logProxyEvent("warn", "proxy_price_storage_wallet_mismatch", {
|
|
1953
|
+
request_wallet: requestPayload.wallet_address,
|
|
1954
|
+
proxy_wallet: account.address
|
|
1955
|
+
});
|
|
1956
|
+
emitProxyTerminalFromStatus(correlation, 403, { reason: "wallet_mismatch" });
|
|
1957
|
+
sendJson(res, 403, {
|
|
1958
|
+
error: "wallet_proof_invalid",
|
|
1959
|
+
message: "wallet proof invalid"
|
|
1960
|
+
});
|
|
1961
|
+
return;
|
|
1962
|
+
}
|
|
1934
1963
|
emitProxyEvent("storage.call", "start", correlation, { target: "price-storage" });
|
|
1935
1964
|
const walletSignature = await createBackendWalletSignature(
|
|
1936
1965
|
"POST",
|
|
@@ -1939,8 +1968,7 @@ async function startProxy(options) {
|
|
|
1939
1968
|
);
|
|
1940
1969
|
if (!walletSignature) {
|
|
1941
1970
|
logProxyEvent("warn", "proxy_price_storage_wallet_signature_missing");
|
|
1942
|
-
res
|
|
1943
|
-
res.end(createWalletRequiredBody());
|
|
1971
|
+
sendWalletRequired(res);
|
|
1944
1972
|
emitProxyTerminalFromStatus(correlation, 400, { reason: "wallet_signature_missing" });
|
|
1945
1973
|
return;
|
|
1946
1974
|
}
|
|
@@ -2089,8 +2117,7 @@ async function startProxy(options) {
|
|
|
2089
2117
|
);
|
|
2090
2118
|
if (!walletSignature) {
|
|
2091
2119
|
logProxyEvent("warn", "proxy_payment_settle_wallet_signature_missing");
|
|
2092
|
-
res
|
|
2093
|
-
res.end(createWalletRequiredBody());
|
|
2120
|
+
sendWalletRequired(res);
|
|
2094
2121
|
emitProxyTerminalFromStatus(correlation, 400, { reason: "wallet_signature_missing" });
|
|
2095
2122
|
return;
|
|
2096
2123
|
}
|
|
@@ -2198,8 +2225,7 @@ async function startProxy(options) {
|
|
|
2198
2225
|
);
|
|
2199
2226
|
if (!walletSignature) {
|
|
2200
2227
|
logProxyEvent("warn", "proxy_upload_wallet_signature_missing");
|
|
2201
|
-
res
|
|
2202
|
-
res.end(createWalletRequiredBody());
|
|
2228
|
+
sendWalletRequired(res);
|
|
2203
2229
|
emitProxyTerminalFromStatus(correlation, 400, { reason: "wallet_signature_missing" });
|
|
2204
2230
|
return;
|
|
2205
2231
|
}
|
|
@@ -2246,8 +2272,7 @@ async function startProxy(options) {
|
|
|
2246
2272
|
);
|
|
2247
2273
|
if (!settleWalletSignature) {
|
|
2248
2274
|
logProxyEvent("warn", "proxy_upload_settle_signature_missing");
|
|
2249
|
-
res
|
|
2250
|
-
res.end(createWalletRequiredBody());
|
|
2275
|
+
sendWalletRequired(res);
|
|
2251
2276
|
emitProxyTerminalFromStatus(correlation, 400, { reason: "settle_signature_missing" });
|
|
2252
2277
|
return;
|
|
2253
2278
|
}
|
|
@@ -2387,8 +2412,7 @@ async function startProxy(options) {
|
|
|
2387
2412
|
);
|
|
2388
2413
|
if (!walletSignature) {
|
|
2389
2414
|
logProxyEvent("warn", "proxy_upload_confirm_wallet_signature_missing");
|
|
2390
|
-
res
|
|
2391
|
-
res.end(createWalletRequiredBody());
|
|
2415
|
+
sendWalletRequired(res);
|
|
2392
2416
|
emitProxyTerminalFromStatus(correlation, 400, { reason: "wallet_signature_missing" });
|
|
2393
2417
|
return;
|
|
2394
2418
|
}
|
|
@@ -2482,8 +2506,7 @@ async function startProxy(options) {
|
|
|
2482
2506
|
);
|
|
2483
2507
|
if (!walletSignature) {
|
|
2484
2508
|
logProxyEvent("warn", "proxy_ls_wallet_signature_missing");
|
|
2485
|
-
res
|
|
2486
|
-
res.end(createWalletRequiredBody());
|
|
2509
|
+
sendWalletRequired(res);
|
|
2487
2510
|
emitProxyTerminalFromStatus(correlation, 400, { reason: "wallet_signature_missing" });
|
|
2488
2511
|
return;
|
|
2489
2512
|
}
|
|
@@ -2577,8 +2600,7 @@ async function startProxy(options) {
|
|
|
2577
2600
|
);
|
|
2578
2601
|
if (!walletSignature) {
|
|
2579
2602
|
logProxyEvent("warn", "proxy_download_wallet_signature_missing");
|
|
2580
|
-
res
|
|
2581
|
-
res.end(createWalletRequiredBody());
|
|
2603
|
+
sendWalletRequired(res);
|
|
2582
2604
|
emitProxyTerminalFromStatus(correlation, 400, { reason: "wallet_signature_missing" });
|
|
2583
2605
|
return;
|
|
2584
2606
|
}
|
|
@@ -2694,8 +2716,7 @@ async function startProxy(options) {
|
|
|
2694
2716
|
);
|
|
2695
2717
|
if (!walletSignature) {
|
|
2696
2718
|
logProxyEvent("warn", "proxy_delete_wallet_signature_missing");
|
|
2697
|
-
res
|
|
2698
|
-
res.end(createWalletRequiredBody());
|
|
2719
|
+
sendWalletRequired(res);
|
|
2699
2720
|
emitProxyTerminalFromStatus(correlation, 400, { reason: "wallet_signature_missing" });
|
|
2700
2721
|
return;
|
|
2701
2722
|
}
|
|
@@ -2765,10 +2786,14 @@ async function startProxy(options) {
|
|
|
2765
2786
|
sendJson(res, 200, response);
|
|
2766
2787
|
return;
|
|
2767
2788
|
}
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2789
|
+
if (MNEMOSPARK_PROXY_VERBOSE_404) {
|
|
2790
|
+
sendJson(res, 404, {
|
|
2791
|
+
error: "Not found",
|
|
2792
|
+
message: "Supported paths: /health and /mnemospark/* storage endpoints"
|
|
2793
|
+
});
|
|
2794
|
+
} else {
|
|
2795
|
+
sendJson(res, 404, { error: "Not found" });
|
|
2796
|
+
}
|
|
2772
2797
|
});
|
|
2773
2798
|
const tryListen = (attempt) => {
|
|
2774
2799
|
return new Promise((resolveAttempt, rejectAttempt) => {
|
|
@@ -4114,7 +4139,8 @@ var priceStorageSchema = {
|
|
|
4114
4139
|
args: [
|
|
4115
4140
|
{ name: "wallet-address", aliases: ["wallet"], required: true },
|
|
4116
4141
|
{ name: "object-id", aliases: ["object"], required: true },
|
|
4117
|
-
|
|
4142
|
+
// Optional: omit when the object exists in local SQLite after backup; CLI resolves sha256 from state.db.
|
|
4143
|
+
{ name: "object-id-hash", aliases: ["hash"] },
|
|
4118
4144
|
{ name: "gb", required: true },
|
|
4119
4145
|
{ name: "provider", required: true },
|
|
4120
4146
|
{ name: "region", required: true }
|
|
@@ -4206,7 +4232,7 @@ var TAR_OVERHEAD_BYTES = 10 * 1024 * 1024;
|
|
|
4206
4232
|
var QUOTE_VALIDITY_USER_NOTE = "Quotes are valid for one hour. Please run price-storage again if you need a new quote.";
|
|
4207
4233
|
var MNEMOSPARK_SUPPORT_EMAIL = "pluggedin@mnemospark.ai";
|
|
4208
4234
|
var CLOUD_HELP_FOOTER_STATE = "Local state: mnemospark records quotes, objects, payments, cron jobs, friendly names, and operation metadata in ~/.openclaw/mnemospark/state.db (SQLite). For troubleshooting and correlation, commands and the HTTP proxy append structured JSON lines to ~/.openclaw/mnemospark/events.jsonl. Monthly storage billing jobs are listed in ~/.openclaw/cron/jobs.json for OpenClaw scheduling.";
|
|
4209
|
-
var REQUIRED_PRICE_STORAGE = "wallet-address:, object-id:, object-id-hash
|
|
4235
|
+
var REQUIRED_PRICE_STORAGE = "wallet-address:, object-id:, gb:, provider:, region: (object-id-hash: optional if the object exists in local SQLite after backup)";
|
|
4210
4236
|
var REQUIRED_UPLOAD = "quote-id:, wallet-address:, object-id:, object-id-hash:";
|
|
4211
4237
|
var REQUIRED_BACKUP = "<file|directory> and name:<friendly-name>";
|
|
4212
4238
|
var REQUIRED_PAYMENT_SETTLE = "wallet-address: and (quote-id: | renewal:true with object-key:)";
|
|
@@ -4236,10 +4262,10 @@ var CLOUD_HELP_TEXT = [
|
|
|
4236
4262
|
" Purpose: create a local tar+gzip archive under ~/.openclaw/mnemospark/backup (filename from sanitized friendly name) and record metadata in SQLite for later price-storage and upload.",
|
|
4237
4263
|
" Required: " + REQUIRED_BACKUP,
|
|
4238
4264
|
"",
|
|
4239
|
-
"\u2022 `/mnemospark cloud price-storage wallet-address:<addr> object-id:<id> object-id-hash:<hash> gb:<gb> provider:aws region:us-east-1`",
|
|
4240
|
-
" Purpose: request a storage quote before upload (defaults shown; override `provider:` / `region:` for other regions).",
|
|
4265
|
+
"\u2022 `/mnemospark cloud price-storage wallet-address:<addr> object-id:<id> [object-id-hash:<hash>] gb:<gb> provider:aws region:us-east-1`",
|
|
4266
|
+
" Purpose: request a storage quote before upload (defaults shown; override `provider:` / `region:` for other regions). Omit `object-id-hash:` when the object is already in local SQLite (e.g. after backup); mnemospark reads sha256 from ~/.openclaw/mnemospark/state.db.",
|
|
4241
4267
|
" Required: " + REQUIRED_PRICE_STORAGE,
|
|
4242
|
-
" Shorter: `wallet:\u2026 object:\u2026 hash:\u2026 gb:\u2026 provider:\u2026 region:\u2026`",
|
|
4268
|
+
" Shorter: `wallet:\u2026 object:\u2026 [hash:\u2026] gb:\u2026 provider:\u2026 region:\u2026`",
|
|
4243
4269
|
"",
|
|
4244
4270
|
"\u2022 `/mnemospark cloud upload quote-id:<quote-id> wallet-address:<addr> object-id:<id> object-id-hash:<hash> [name:<friendly-name>] [async:true] [orchestrator:<inline|subagent>] [timeout-seconds:<n>]`",
|
|
4245
4271
|
" Purpose: upload an encrypted object using a valid quote-id.",
|
|
@@ -4450,6 +4476,41 @@ function stripAsyncControlFlags(args) {
|
|
|
4450
4476
|
function mergeArgParseWarnings(a, b) {
|
|
4451
4477
|
return [...a, ...b];
|
|
4452
4478
|
}
|
|
4479
|
+
async function resolvePriceStorageHashFromDatastore(datastore, partial) {
|
|
4480
|
+
await datastore.ensureReady();
|
|
4481
|
+
const row = await datastore.findObjectById(partial.object_id.trim());
|
|
4482
|
+
const wallet = partial.wallet_address.trim().toLowerCase();
|
|
4483
|
+
if (!row) {
|
|
4484
|
+
return {
|
|
4485
|
+
ok: false,
|
|
4486
|
+
message: "Cannot resolve object-id-hash: no object found in local SQLite for this object-id. Run backup first, or pass --object-id-hash explicitly."
|
|
4487
|
+
};
|
|
4488
|
+
}
|
|
4489
|
+
if (row.wallet_address.trim().toLowerCase() !== wallet) {
|
|
4490
|
+
return {
|
|
4491
|
+
ok: false,
|
|
4492
|
+
message: "Cannot resolve object-id-hash: wallet-address does not match the object record in ~/.openclaw/mnemospark/state.db."
|
|
4493
|
+
};
|
|
4494
|
+
}
|
|
4495
|
+
const sha = row.sha256?.trim();
|
|
4496
|
+
if (!sha) {
|
|
4497
|
+
return {
|
|
4498
|
+
ok: false,
|
|
4499
|
+
message: "Cannot resolve object-id-hash: local object record has no sha256 yet. Run backup first, or pass --object-id-hash explicitly."
|
|
4500
|
+
};
|
|
4501
|
+
}
|
|
4502
|
+
return {
|
|
4503
|
+
ok: true,
|
|
4504
|
+
request: {
|
|
4505
|
+
wallet_address: partial.wallet_address.trim(),
|
|
4506
|
+
object_id: partial.object_id.trim(),
|
|
4507
|
+
object_id_hash: sha.replace(/\s/g, ""),
|
|
4508
|
+
gb: partial.gb,
|
|
4509
|
+
provider: partial.provider.trim(),
|
|
4510
|
+
region: partial.region.trim()
|
|
4511
|
+
}
|
|
4512
|
+
};
|
|
4513
|
+
}
|
|
4453
4514
|
function parseCloudArgs(args) {
|
|
4454
4515
|
const trimmed = args?.trim() ?? "";
|
|
4455
4516
|
if (!trimmed) {
|
|
@@ -4519,18 +4580,38 @@ function parseCloudArgs(args) {
|
|
|
4519
4580
|
}
|
|
4520
4581
|
const flags = valuesToStringRecord(parsed.values);
|
|
4521
4582
|
const gb = Number.parseFloat(flags.gb ?? "");
|
|
4522
|
-
const
|
|
4523
|
-
|
|
4524
|
-
|
|
4525
|
-
|
|
4526
|
-
|
|
4527
|
-
|
|
4528
|
-
region: flags.region
|
|
4529
|
-
});
|
|
4530
|
-
if (!request) {
|
|
4583
|
+
const hashRaw = flags["object-id-hash"]?.trim();
|
|
4584
|
+
const walletAddress = flags["wallet-address"]?.trim();
|
|
4585
|
+
const objectId = flags["object-id"]?.trim();
|
|
4586
|
+
const provider = flags.provider?.trim();
|
|
4587
|
+
const region = flags.region?.trim();
|
|
4588
|
+
if (!walletAddress || !objectId || !provider || !region || !Number.isFinite(gb)) {
|
|
4531
4589
|
return { mode: "price-storage-invalid" };
|
|
4532
4590
|
}
|
|
4533
|
-
|
|
4591
|
+
if (hashRaw) {
|
|
4592
|
+
const request = parsePriceStorageQuoteRequest({
|
|
4593
|
+
wallet_address: walletAddress,
|
|
4594
|
+
object_id: objectId,
|
|
4595
|
+
object_id_hash: hashRaw,
|
|
4596
|
+
gb,
|
|
4597
|
+
provider,
|
|
4598
|
+
region
|
|
4599
|
+
});
|
|
4600
|
+
if (!request) {
|
|
4601
|
+
return { mode: "price-storage-invalid" };
|
|
4602
|
+
}
|
|
4603
|
+
return { mode: "price-storage", priceStorageRequest: request };
|
|
4604
|
+
}
|
|
4605
|
+
return {
|
|
4606
|
+
mode: "price-storage-resolve-hash",
|
|
4607
|
+
priceStoragePartial: {
|
|
4608
|
+
wallet_address: walletAddress,
|
|
4609
|
+
object_id: objectId,
|
|
4610
|
+
gb,
|
|
4611
|
+
provider,
|
|
4612
|
+
region
|
|
4613
|
+
}
|
|
4614
|
+
};
|
|
4534
4615
|
}
|
|
4535
4616
|
if (subcommand === "upload") {
|
|
4536
4617
|
const parsed = parseCommandArgs(rest, uploadSchema);
|
|
@@ -6667,10 +6748,23 @@ operation-id: ${operationId}`,
|
|
|
6667
6748
|
};
|
|
6668
6749
|
}
|
|
6669
6750
|
}
|
|
6670
|
-
if (parsed.mode === "price-storage") {
|
|
6751
|
+
if (parsed.mode === "price-storage" || parsed.mode === "price-storage-resolve-hash") {
|
|
6752
|
+
let priceStorageRequest;
|
|
6753
|
+
if (parsed.mode === "price-storage-resolve-hash") {
|
|
6754
|
+
const resolved = await resolvePriceStorageHashFromDatastore(
|
|
6755
|
+
datastore,
|
|
6756
|
+
parsed.priceStoragePartial
|
|
6757
|
+
);
|
|
6758
|
+
if (!resolved.ok) {
|
|
6759
|
+
return { text: resolved.message, isError: true };
|
|
6760
|
+
}
|
|
6761
|
+
priceStorageRequest = resolved.request;
|
|
6762
|
+
} else {
|
|
6763
|
+
priceStorageRequest = parsed.priceStorageRequest;
|
|
6764
|
+
}
|
|
6671
6765
|
const correlation = buildRequestCorrelation();
|
|
6672
6766
|
try {
|
|
6673
|
-
const quote = await requestPriceStorageQuote(
|
|
6767
|
+
const quote = await requestPriceStorageQuote(priceStorageRequest, {
|
|
6674
6768
|
...options.proxyQuoteOptions,
|
|
6675
6769
|
correlation
|
|
6676
6770
|
});
|
|
@@ -6728,8 +6822,8 @@ operation-id: ${operationId}`,
|
|
|
6728
6822
|
{
|
|
6729
6823
|
operation_id: correlation.operationId,
|
|
6730
6824
|
trace_id: correlation.traceId,
|
|
6731
|
-
wallet_address:
|
|
6732
|
-
object_id:
|
|
6825
|
+
wallet_address: priceStorageRequest.wallet_address,
|
|
6826
|
+
object_id: priceStorageRequest.object_id,
|
|
6733
6827
|
status: "failed"
|
|
6734
6828
|
},
|
|
6735
6829
|
mnemosparkHomeDir
|