mnemospark 0.9.2 → 1.0.1
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 +8 -8
- package/dist/cli.js +814 -169
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +10 -2
- package/dist/index.js +811 -237
- package/dist/index.js.map +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/skills/mnemospark/SKILL.md +14 -14
- package/skills/mnemospark/references/commands.md +7 -5
package/dist/cli.js
CHANGED
|
@@ -1915,7 +1915,7 @@ async function startProxy(options) {
|
|
|
1915
1915
|
emitProxyTerminalFromStatus(correlation, 400, { reason: "invalid_json" });
|
|
1916
1916
|
sendJson(res, 400, {
|
|
1917
1917
|
error: "Bad request",
|
|
1918
|
-
message: "Invalid JSON body for /
|
|
1918
|
+
message: "Invalid JSON body for /mnemospark cloud price-storage"
|
|
1919
1919
|
});
|
|
1920
1920
|
return;
|
|
1921
1921
|
}
|
|
@@ -1983,7 +1983,7 @@ async function startProxy(options) {
|
|
|
1983
1983
|
});
|
|
1984
1984
|
sendJson(res, 502, {
|
|
1985
1985
|
error: "proxy_error",
|
|
1986
|
-
message: `Failed to forward /
|
|
1986
|
+
message: `Failed to forward /mnemospark cloud price-storage: ${err instanceof Error ? err.message : String(err)}`
|
|
1987
1987
|
});
|
|
1988
1988
|
}
|
|
1989
1989
|
return;
|
|
@@ -2162,7 +2162,7 @@ async function startProxy(options) {
|
|
|
2162
2162
|
emitProxyTerminalFromStatus(correlation, 400, { reason: "invalid_json" });
|
|
2163
2163
|
sendJson(res, 400, {
|
|
2164
2164
|
error: "Bad request",
|
|
2165
|
-
message: "Invalid JSON body for /
|
|
2165
|
+
message: "Invalid JSON body for /mnemospark cloud upload"
|
|
2166
2166
|
});
|
|
2167
2167
|
return;
|
|
2168
2168
|
}
|
|
@@ -2225,7 +2225,7 @@ async function startProxy(options) {
|
|
|
2225
2225
|
error: "insufficient_balance",
|
|
2226
2226
|
message: `Insufficient USDC balance. Current: ${sufficiency.info.balanceUSD}, Required: ${requiredUSD}`,
|
|
2227
2227
|
wallet: requestPayload.wallet_address,
|
|
2228
|
-
help: `Fund wallet ${requestPayload.wallet_address} on Base before running /
|
|
2228
|
+
help: `Fund wallet ${requestPayload.wallet_address} on Base before running /mnemospark cloud upload`
|
|
2229
2229
|
});
|
|
2230
2230
|
return;
|
|
2231
2231
|
}
|
|
@@ -2333,7 +2333,7 @@ async function startProxy(options) {
|
|
|
2333
2333
|
});
|
|
2334
2334
|
sendJson(res, 502, {
|
|
2335
2335
|
error: "proxy_error",
|
|
2336
|
-
message: `Failed to forward /
|
|
2336
|
+
message: `Failed to forward /mnemospark cloud upload: ${err instanceof Error ? err.message : String(err)}`
|
|
2337
2337
|
});
|
|
2338
2338
|
}
|
|
2339
2339
|
return;
|
|
@@ -2351,7 +2351,7 @@ async function startProxy(options) {
|
|
|
2351
2351
|
emitProxyTerminalFromStatus(correlation, 400, { reason: "invalid_json" });
|
|
2352
2352
|
sendJson(res, 400, {
|
|
2353
2353
|
error: "Bad request",
|
|
2354
|
-
message: "Invalid JSON body for /
|
|
2354
|
+
message: "Invalid JSON body for /mnemospark cloud upload/confirm"
|
|
2355
2355
|
});
|
|
2356
2356
|
return;
|
|
2357
2357
|
}
|
|
@@ -2432,7 +2432,7 @@ async function startProxy(options) {
|
|
|
2432
2432
|
});
|
|
2433
2433
|
sendJson(res, 502, {
|
|
2434
2434
|
error: "proxy_error",
|
|
2435
|
-
message: `Failed to forward /
|
|
2435
|
+
message: `Failed to forward /mnemospark cloud upload/confirm: ${err instanceof Error ? err.message : String(err)}`
|
|
2436
2436
|
});
|
|
2437
2437
|
}
|
|
2438
2438
|
return;
|
|
@@ -2450,7 +2450,7 @@ async function startProxy(options) {
|
|
|
2450
2450
|
emitProxyTerminalFromStatus(correlation, 400, { reason: "invalid_json" });
|
|
2451
2451
|
sendJson(res, 400, {
|
|
2452
2452
|
error: "Bad request",
|
|
2453
|
-
message: "Invalid JSON body for /
|
|
2453
|
+
message: "Invalid JSON body for /mnemospark cloud ls"
|
|
2454
2454
|
});
|
|
2455
2455
|
return;
|
|
2456
2456
|
}
|
|
@@ -2523,7 +2523,7 @@ async function startProxy(options) {
|
|
|
2523
2523
|
});
|
|
2524
2524
|
sendJson(res, 502, {
|
|
2525
2525
|
error: "proxy_error",
|
|
2526
|
-
message: `Failed to forward /
|
|
2526
|
+
message: `Failed to forward /mnemospark cloud ls: ${err instanceof Error ? err.message : String(err)}`
|
|
2527
2527
|
});
|
|
2528
2528
|
}
|
|
2529
2529
|
return;
|
|
@@ -2543,7 +2543,7 @@ async function startProxy(options) {
|
|
|
2543
2543
|
emitProxyTerminalFromStatus(correlation, 400, { reason: "invalid_json" });
|
|
2544
2544
|
sendJson(res, 400, {
|
|
2545
2545
|
error: "Bad request",
|
|
2546
|
-
message: "Invalid JSON body for /
|
|
2546
|
+
message: "Invalid JSON body for /mnemospark cloud download"
|
|
2547
2547
|
});
|
|
2548
2548
|
return;
|
|
2549
2549
|
}
|
|
@@ -2644,7 +2644,7 @@ async function startProxy(options) {
|
|
|
2644
2644
|
});
|
|
2645
2645
|
sendJson(res, 502, {
|
|
2646
2646
|
error: "proxy_error",
|
|
2647
|
-
message: `Failed to forward /
|
|
2647
|
+
message: `Failed to forward /mnemospark cloud download: ${err instanceof Error ? err.message : String(err)}`
|
|
2648
2648
|
});
|
|
2649
2649
|
}
|
|
2650
2650
|
return;
|
|
@@ -2662,7 +2662,7 @@ async function startProxy(options) {
|
|
|
2662
2662
|
emitProxyTerminalFromStatus(correlation, 400, { reason: "invalid_json" });
|
|
2663
2663
|
sendJson(res, 400, {
|
|
2664
2664
|
error: "Bad request",
|
|
2665
|
-
message: "Invalid JSON body for /
|
|
2665
|
+
message: "Invalid JSON body for /mnemospark cloud delete"
|
|
2666
2666
|
});
|
|
2667
2667
|
return;
|
|
2668
2668
|
}
|
|
@@ -2739,7 +2739,7 @@ async function startProxy(options) {
|
|
|
2739
2739
|
});
|
|
2740
2740
|
sendJson(res, 502, {
|
|
2741
2741
|
error: "proxy_error",
|
|
2742
|
-
message: `Failed to forward /
|
|
2742
|
+
message: `Failed to forward /mnemospark cloud delete: ${err instanceof Error ? err.message : String(err)}`
|
|
2743
2743
|
});
|
|
2744
2744
|
}
|
|
2745
2745
|
return;
|
|
@@ -2965,6 +2965,10 @@ var pkg = require2(join6(__dirname, "..", "package.json"));
|
|
|
2965
2965
|
var VERSION = pkg.version;
|
|
2966
2966
|
var USER_AGENT = `mnemospark/${VERSION}`;
|
|
2967
2967
|
|
|
2968
|
+
// src/mnemospark-handler.ts
|
|
2969
|
+
import { existsSync, readFileSync } from "fs";
|
|
2970
|
+
import { privateKeyToAccount as privateKeyToAccount6 } from "viem/accounts";
|
|
2971
|
+
|
|
2968
2972
|
// src/cloud-command.ts
|
|
2969
2973
|
import { spawn } from "child_process";
|
|
2970
2974
|
import {
|
|
@@ -3761,6 +3765,425 @@ async function createCloudDatastore(homeDir) {
|
|
|
3761
3765
|
};
|
|
3762
3766
|
}
|
|
3763
3767
|
|
|
3768
|
+
// src/args/normalize.ts
|
|
3769
|
+
function normalizeSmartQuotes(input) {
|
|
3770
|
+
return input.replace(/[\u201C\u201D]/g, '"').replace(/[\u2018\u2019]/g, "'");
|
|
3771
|
+
}
|
|
3772
|
+
function normalizeFlagPositionDashes(input) {
|
|
3773
|
+
const warnings = [];
|
|
3774
|
+
const pattern = /(^|\s)[\u2013\u2014](?=[A-Za-z_][A-Za-z0-9_-]*)/g;
|
|
3775
|
+
let changed = false;
|
|
3776
|
+
const text = input.replace(pattern, (m, prefix) => {
|
|
3777
|
+
changed = true;
|
|
3778
|
+
return `${prefix}--`;
|
|
3779
|
+
});
|
|
3780
|
+
if (changed) {
|
|
3781
|
+
warnings.push("Normalized en/em dash in flag position to ASCII double hyphen.");
|
|
3782
|
+
}
|
|
3783
|
+
return { text, warnings };
|
|
3784
|
+
}
|
|
3785
|
+
function normalizeInputForParsing(input) {
|
|
3786
|
+
const warnings = [];
|
|
3787
|
+
let text = normalizeSmartQuotes(input);
|
|
3788
|
+
const dashNorm = normalizeFlagPositionDashes(text);
|
|
3789
|
+
text = dashNorm.text;
|
|
3790
|
+
warnings.push(...dashNorm.warnings);
|
|
3791
|
+
return { text, warnings };
|
|
3792
|
+
}
|
|
3793
|
+
|
|
3794
|
+
// src/args/suggest.ts
|
|
3795
|
+
function levenshtein(a, b) {
|
|
3796
|
+
const m = a.length;
|
|
3797
|
+
const n = b.length;
|
|
3798
|
+
const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));
|
|
3799
|
+
for (let i = 0; i <= m; i++) dp[i][0] = i;
|
|
3800
|
+
for (let j = 0; j <= n; j++) dp[0][j] = j;
|
|
3801
|
+
for (let i = 1; i <= m; i++) {
|
|
3802
|
+
for (let j = 1; j <= n; j++) {
|
|
3803
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
3804
|
+
dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + cost);
|
|
3805
|
+
}
|
|
3806
|
+
}
|
|
3807
|
+
return dp[m][n];
|
|
3808
|
+
}
|
|
3809
|
+
function suggestNearestKey(raw, candidates, maxDistance = 2) {
|
|
3810
|
+
const lower = raw.toLowerCase();
|
|
3811
|
+
let best = null;
|
|
3812
|
+
let bestDist = maxDistance + 1;
|
|
3813
|
+
for (const c of candidates) {
|
|
3814
|
+
const d = levenshtein(lower, c.toLowerCase());
|
|
3815
|
+
if (d < bestDist) {
|
|
3816
|
+
bestDist = d;
|
|
3817
|
+
best = c;
|
|
3818
|
+
}
|
|
3819
|
+
}
|
|
3820
|
+
return bestDist <= maxDistance ? best : null;
|
|
3821
|
+
}
|
|
3822
|
+
|
|
3823
|
+
// src/args/parser.ts
|
|
3824
|
+
function canonicalizeKey(rawKey) {
|
|
3825
|
+
return rawKey.normalize("NFKC").replace(/[\u2010\u2011\u2012\u2013\u2014\u2015\u2212]/g, "-").replace(/_/g, "-").toLowerCase().trim();
|
|
3826
|
+
}
|
|
3827
|
+
function buildAliasMap(schema) {
|
|
3828
|
+
const map = /* @__PURE__ */ new Map();
|
|
3829
|
+
for (const spec of schema.args) {
|
|
3830
|
+
map.set(canonicalizeKey(spec.name), spec);
|
|
3831
|
+
for (const alias of spec.aliases ?? []) {
|
|
3832
|
+
map.set(canonicalizeKey(alias), spec);
|
|
3833
|
+
}
|
|
3834
|
+
}
|
|
3835
|
+
return map;
|
|
3836
|
+
}
|
|
3837
|
+
function tokenize(input) {
|
|
3838
|
+
const tokens = [];
|
|
3839
|
+
let i = 0;
|
|
3840
|
+
while (i < input.length) {
|
|
3841
|
+
while (i < input.length && /\s/.test(input[i])) i++;
|
|
3842
|
+
if (i >= input.length) break;
|
|
3843
|
+
let raw = "";
|
|
3844
|
+
let value = "";
|
|
3845
|
+
if (input[i] === '"' || input[i] === "'") {
|
|
3846
|
+
const quote = input[i++];
|
|
3847
|
+
raw += quote;
|
|
3848
|
+
while (i < input.length) {
|
|
3849
|
+
const ch = input[i++];
|
|
3850
|
+
raw += ch;
|
|
3851
|
+
if (ch === "\\") {
|
|
3852
|
+
if (i < input.length) {
|
|
3853
|
+
const next = input[i++];
|
|
3854
|
+
raw += next;
|
|
3855
|
+
value += next;
|
|
3856
|
+
}
|
|
3857
|
+
continue;
|
|
3858
|
+
}
|
|
3859
|
+
if (ch === quote) {
|
|
3860
|
+
break;
|
|
3861
|
+
}
|
|
3862
|
+
value += ch;
|
|
3863
|
+
}
|
|
3864
|
+
tokens.push({ raw, value });
|
|
3865
|
+
continue;
|
|
3866
|
+
}
|
|
3867
|
+
while (i < input.length && !/\s/.test(input[i])) {
|
|
3868
|
+
const ch = input[i++];
|
|
3869
|
+
raw += ch;
|
|
3870
|
+
value += ch;
|
|
3871
|
+
}
|
|
3872
|
+
tokens.push({ raw, value });
|
|
3873
|
+
}
|
|
3874
|
+
return tokens;
|
|
3875
|
+
}
|
|
3876
|
+
function resolveKey(rawKey, aliasMap, schema, allCanonicalNames) {
|
|
3877
|
+
const canonical = canonicalizeKey(rawKey);
|
|
3878
|
+
const spec = aliasMap.get(canonical);
|
|
3879
|
+
if (!spec) {
|
|
3880
|
+
if (schema.allowUnknown) return { key: canonical };
|
|
3881
|
+
const suggestion = suggestNearestKey(rawKey, allCanonicalNames);
|
|
3882
|
+
const hint = suggestion ? ` Did you mean "${suggestion}"?` : "";
|
|
3883
|
+
return { error: `Unknown argument "${rawKey}".${hint}` };
|
|
3884
|
+
}
|
|
3885
|
+
return { key: spec.name, spec };
|
|
3886
|
+
}
|
|
3887
|
+
function addValue(out, key, value, spec) {
|
|
3888
|
+
const existing = out[key];
|
|
3889
|
+
if (existing === void 0) {
|
|
3890
|
+
out[key] = spec?.repeatable ? [value] : value;
|
|
3891
|
+
return null;
|
|
3892
|
+
}
|
|
3893
|
+
if (!spec?.repeatable) {
|
|
3894
|
+
return `Duplicate argument "${key}".`;
|
|
3895
|
+
}
|
|
3896
|
+
if (Array.isArray(existing)) {
|
|
3897
|
+
existing.push(value);
|
|
3898
|
+
} else {
|
|
3899
|
+
out[key] = [existing, value];
|
|
3900
|
+
}
|
|
3901
|
+
return null;
|
|
3902
|
+
}
|
|
3903
|
+
function collectCanonicalNames(schema) {
|
|
3904
|
+
const names = /* @__PURE__ */ new Set();
|
|
3905
|
+
for (const spec of schema.args) {
|
|
3906
|
+
names.add(spec.name);
|
|
3907
|
+
for (const a of spec.aliases ?? []) {
|
|
3908
|
+
names.add(a);
|
|
3909
|
+
}
|
|
3910
|
+
}
|
|
3911
|
+
return [...names];
|
|
3912
|
+
}
|
|
3913
|
+
function looksLikeDelimitedArgToken(token) {
|
|
3914
|
+
return /^[A-Za-z_][A-Za-z0-9_-]*[:=]/.test(token);
|
|
3915
|
+
}
|
|
3916
|
+
function tryParseDelimitedToken(token, delimiter, aliasMap, schema, allCanonicalNames, out) {
|
|
3917
|
+
const idx = token.indexOf(delimiter);
|
|
3918
|
+
if (idx <= 0) return { handled: false };
|
|
3919
|
+
const keyPart = token.slice(0, idx);
|
|
3920
|
+
if (!/^[A-Za-z_][A-Za-z0-9_-]*$/.test(keyPart)) return { handled: false };
|
|
3921
|
+
const rawKey = keyPart;
|
|
3922
|
+
const rawValue = token.slice(idx + 1);
|
|
3923
|
+
if (rawValue === "") {
|
|
3924
|
+
return { handled: true, error: `Empty value for argument "${rawKey}".` };
|
|
3925
|
+
}
|
|
3926
|
+
const resolved = resolveKey(rawKey, aliasMap, schema, allCanonicalNames);
|
|
3927
|
+
if (resolved.error) {
|
|
3928
|
+
return { handled: true, error: resolved.error };
|
|
3929
|
+
}
|
|
3930
|
+
const dupErr = addValue(out, resolved.key, rawValue, resolved.spec);
|
|
3931
|
+
if (dupErr) {
|
|
3932
|
+
return { handled: true, error: dupErr };
|
|
3933
|
+
}
|
|
3934
|
+
return { handled: true };
|
|
3935
|
+
}
|
|
3936
|
+
function parseCommandArgs(input, schema) {
|
|
3937
|
+
const warnings = [];
|
|
3938
|
+
const errors = [];
|
|
3939
|
+
const norm = normalizeInputForParsing(input);
|
|
3940
|
+
const normalized = norm.text;
|
|
3941
|
+
warnings.push(...norm.warnings);
|
|
3942
|
+
const tokens = tokenize(normalized);
|
|
3943
|
+
const aliasMap = buildAliasMap(schema);
|
|
3944
|
+
const allCanonicalNames = collectCanonicalNames(schema);
|
|
3945
|
+
const values = {};
|
|
3946
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
3947
|
+
const token = tokens[i].value;
|
|
3948
|
+
{
|
|
3949
|
+
const parsed = tryParseDelimitedToken(
|
|
3950
|
+
token,
|
|
3951
|
+
":",
|
|
3952
|
+
aliasMap,
|
|
3953
|
+
schema,
|
|
3954
|
+
allCanonicalNames,
|
|
3955
|
+
values
|
|
3956
|
+
);
|
|
3957
|
+
if (parsed.handled) {
|
|
3958
|
+
if (parsed.error) errors.push(parsed.error);
|
|
3959
|
+
continue;
|
|
3960
|
+
}
|
|
3961
|
+
}
|
|
3962
|
+
{
|
|
3963
|
+
const parsed = tryParseDelimitedToken(
|
|
3964
|
+
token,
|
|
3965
|
+
"=",
|
|
3966
|
+
aliasMap,
|
|
3967
|
+
schema,
|
|
3968
|
+
allCanonicalNames,
|
|
3969
|
+
values
|
|
3970
|
+
);
|
|
3971
|
+
if (parsed.handled) {
|
|
3972
|
+
if (parsed.error) errors.push(parsed.error);
|
|
3973
|
+
continue;
|
|
3974
|
+
}
|
|
3975
|
+
}
|
|
3976
|
+
if (token.startsWith("--")) {
|
|
3977
|
+
const rawKey = token.slice(2);
|
|
3978
|
+
if (!rawKey) {
|
|
3979
|
+
errors.push('Encountered "--" without an argument name.');
|
|
3980
|
+
continue;
|
|
3981
|
+
}
|
|
3982
|
+
const resolved = resolveKey(rawKey, aliasMap, schema, allCanonicalNames);
|
|
3983
|
+
if (resolved.error) {
|
|
3984
|
+
errors.push(resolved.error);
|
|
3985
|
+
continue;
|
|
3986
|
+
}
|
|
3987
|
+
const next = tokens[i + 1];
|
|
3988
|
+
if (!next) {
|
|
3989
|
+
if (resolved.spec?.bareBoolean) {
|
|
3990
|
+
const dupErr2 = addValue(values, resolved.key, "true", resolved.spec);
|
|
3991
|
+
if (dupErr2) errors.push(dupErr2);
|
|
3992
|
+
continue;
|
|
3993
|
+
}
|
|
3994
|
+
errors.push(`Missing value for argument "${resolved.key}".`);
|
|
3995
|
+
continue;
|
|
3996
|
+
}
|
|
3997
|
+
if (next.value.startsWith("--")) {
|
|
3998
|
+
if (resolved.spec?.bareBoolean) {
|
|
3999
|
+
const dupErr2 = addValue(values, resolved.key, "true", resolved.spec);
|
|
4000
|
+
if (dupErr2) errors.push(dupErr2);
|
|
4001
|
+
continue;
|
|
4002
|
+
}
|
|
4003
|
+
errors.push(`Missing value for argument "${resolved.key}".`);
|
|
4004
|
+
continue;
|
|
4005
|
+
}
|
|
4006
|
+
if (resolved.spec?.bareBoolean && looksLikeDelimitedArgToken(next.value)) {
|
|
4007
|
+
const dupErr2 = addValue(values, resolved.key, "true", resolved.spec);
|
|
4008
|
+
if (dupErr2) errors.push(dupErr2);
|
|
4009
|
+
continue;
|
|
4010
|
+
}
|
|
4011
|
+
const dupErr = addValue(values, resolved.key, next.value, resolved.spec);
|
|
4012
|
+
if (dupErr) errors.push(dupErr);
|
|
4013
|
+
i += 1;
|
|
4014
|
+
continue;
|
|
4015
|
+
}
|
|
4016
|
+
errors.push(`Unexpected token "${token}". Use key:value, key=value, or --key value.`);
|
|
4017
|
+
}
|
|
4018
|
+
for (const spec of schema.args) {
|
|
4019
|
+
if (spec.required && values[spec.name] === void 0) {
|
|
4020
|
+
errors.push(`Missing required argument "${spec.name}".`);
|
|
4021
|
+
}
|
|
4022
|
+
}
|
|
4023
|
+
if (errors.length > 0) {
|
|
4024
|
+
return {
|
|
4025
|
+
ok: false,
|
|
4026
|
+
normalizedInput: normalized,
|
|
4027
|
+
errors,
|
|
4028
|
+
warnings
|
|
4029
|
+
};
|
|
4030
|
+
}
|
|
4031
|
+
return {
|
|
4032
|
+
ok: true,
|
|
4033
|
+
normalizedInput: normalized,
|
|
4034
|
+
values,
|
|
4035
|
+
warnings
|
|
4036
|
+
};
|
|
4037
|
+
}
|
|
4038
|
+
function valuesToStringRecord(values) {
|
|
4039
|
+
const out = {};
|
|
4040
|
+
for (const [k, v] of Object.entries(values)) {
|
|
4041
|
+
out[k] = Array.isArray(v) ? v[v.length - 1] : v;
|
|
4042
|
+
}
|
|
4043
|
+
return out;
|
|
4044
|
+
}
|
|
4045
|
+
|
|
4046
|
+
// src/mnemospark-route.ts
|
|
4047
|
+
function parseVerboseToken(token) {
|
|
4048
|
+
const t = token.trim();
|
|
4049
|
+
const idx = t.indexOf(":");
|
|
4050
|
+
if (idx < 0) {
|
|
4051
|
+
return { name: t.toLowerCase(), ok: true };
|
|
4052
|
+
}
|
|
4053
|
+
const key = t.slice(0, idx).trim();
|
|
4054
|
+
const val = t.slice(idx + 1).trim().toLowerCase();
|
|
4055
|
+
if (!key) return { name: "", ok: false };
|
|
4056
|
+
if (val === "true") return { name: key.toLowerCase(), ok: true };
|
|
4057
|
+
return { name: key.toLowerCase(), ok: false };
|
|
4058
|
+
}
|
|
4059
|
+
function firstTokenAndRest(input) {
|
|
4060
|
+
const t = input.trim();
|
|
4061
|
+
if (!t) return { first: "", rest: "" };
|
|
4062
|
+
const spaceIdx = t.search(/\s/);
|
|
4063
|
+
if (spaceIdx === -1) return { first: t, rest: "" };
|
|
4064
|
+
return { first: t.slice(0, spaceIdx), rest: t.slice(spaceIdx + 1).trim() };
|
|
4065
|
+
}
|
|
4066
|
+
function routeMnemosparkArgs(args) {
|
|
4067
|
+
const trimmed = args?.trim() ?? "";
|
|
4068
|
+
if (!trimmed) {
|
|
4069
|
+
return { kind: "root-help" };
|
|
4070
|
+
}
|
|
4071
|
+
const { first, rest } = firstTokenAndRest(trimmed);
|
|
4072
|
+
const parsed = parseVerboseToken(first);
|
|
4073
|
+
if (!parsed.ok) {
|
|
4074
|
+
return {
|
|
4075
|
+
kind: "error",
|
|
4076
|
+
message: `Invalid token "${first}". Use name:true only with value true, or a bare name (e.g. cloud, wallet, help).`
|
|
4077
|
+
};
|
|
4078
|
+
}
|
|
4079
|
+
const head = parsed.name;
|
|
4080
|
+
if (head === "help") {
|
|
4081
|
+
return { kind: "root-help" };
|
|
4082
|
+
}
|
|
4083
|
+
if (head === "cloud") {
|
|
4084
|
+
return { kind: "cloud", rest };
|
|
4085
|
+
}
|
|
4086
|
+
if (head === "wallet") {
|
|
4087
|
+
return { kind: "wallet", rest };
|
|
4088
|
+
}
|
|
4089
|
+
return {
|
|
4090
|
+
kind: "error",
|
|
4091
|
+
message: [
|
|
4092
|
+
`Unknown command "${first}".`,
|
|
4093
|
+
"",
|
|
4094
|
+
"Try:",
|
|
4095
|
+
"\u2022 `/mnemospark help` \u2014 overview",
|
|
4096
|
+
"\u2022 `/mnemospark cloud help` \u2014 cloud commands",
|
|
4097
|
+
"\u2022 `/mnemospark wallet` \u2014 wallet status",
|
|
4098
|
+
"\u2022 `/mnemospark wallet help` \u2014 wallet commands"
|
|
4099
|
+
].join("\n")
|
|
4100
|
+
};
|
|
4101
|
+
}
|
|
4102
|
+
|
|
4103
|
+
// src/arg-schemas.ts
|
|
4104
|
+
var priceStorageSchema = {
|
|
4105
|
+
args: [
|
|
4106
|
+
{ name: "wallet-address", aliases: ["wallet"], required: true },
|
|
4107
|
+
{ name: "object-id", aliases: ["object"], required: true },
|
|
4108
|
+
{ name: "object-id-hash", aliases: ["hash"], required: true },
|
|
4109
|
+
{ name: "gb", required: true },
|
|
4110
|
+
{ name: "provider", required: true },
|
|
4111
|
+
{ name: "region", required: true }
|
|
4112
|
+
]
|
|
4113
|
+
};
|
|
4114
|
+
var uploadSchema = {
|
|
4115
|
+
args: [
|
|
4116
|
+
{ name: "quote-id", aliases: ["quote"], required: true },
|
|
4117
|
+
{ name: "wallet-address", aliases: ["wallet"], required: true },
|
|
4118
|
+
{ name: "object-id", aliases: ["object"], required: true },
|
|
4119
|
+
{ name: "object-id-hash", aliases: ["hash"], required: true },
|
|
4120
|
+
{ name: "name" },
|
|
4121
|
+
{ name: "async", bareBoolean: true },
|
|
4122
|
+
{ name: "orchestrator" },
|
|
4123
|
+
{ name: "timeout-seconds" }
|
|
4124
|
+
]
|
|
4125
|
+
};
|
|
4126
|
+
var backupFlagsSchema = {
|
|
4127
|
+
args: [
|
|
4128
|
+
{ name: "name" },
|
|
4129
|
+
{ name: "async", bareBoolean: true },
|
|
4130
|
+
{ name: "orchestrator" },
|
|
4131
|
+
{ name: "timeout-seconds" }
|
|
4132
|
+
]
|
|
4133
|
+
};
|
|
4134
|
+
var paymentSettleSchema = {
|
|
4135
|
+
args: [
|
|
4136
|
+
{ name: "quote-id", aliases: ["quote"] },
|
|
4137
|
+
{ name: "wallet-address", aliases: ["wallet"], required: true },
|
|
4138
|
+
{ name: "object-id", aliases: ["object"] },
|
|
4139
|
+
{ name: "object-key" },
|
|
4140
|
+
{ name: "storage-price" },
|
|
4141
|
+
{ name: "renewal", bareBoolean: true }
|
|
4142
|
+
]
|
|
4143
|
+
};
|
|
4144
|
+
var lsSchema = {
|
|
4145
|
+
args: [
|
|
4146
|
+
{ name: "wallet-address", aliases: ["wallet"], required: true },
|
|
4147
|
+
{ name: "object-key" },
|
|
4148
|
+
{ name: "name" },
|
|
4149
|
+
{ name: "latest", bareBoolean: true },
|
|
4150
|
+
{ name: "at" },
|
|
4151
|
+
{ name: "location" },
|
|
4152
|
+
{ name: "region" }
|
|
4153
|
+
]
|
|
4154
|
+
};
|
|
4155
|
+
var downloadSchema = {
|
|
4156
|
+
args: [
|
|
4157
|
+
{ name: "wallet-address", aliases: ["wallet"], required: true },
|
|
4158
|
+
{ name: "object-key" },
|
|
4159
|
+
{ name: "name" },
|
|
4160
|
+
{ name: "latest", bareBoolean: true },
|
|
4161
|
+
{ name: "at" },
|
|
4162
|
+
{ name: "location" },
|
|
4163
|
+
{ name: "region" },
|
|
4164
|
+
{ name: "async", bareBoolean: true },
|
|
4165
|
+
{ name: "orchestrator" },
|
|
4166
|
+
{ name: "timeout-seconds" }
|
|
4167
|
+
]
|
|
4168
|
+
};
|
|
4169
|
+
var deleteSchema = {
|
|
4170
|
+
args: [
|
|
4171
|
+
{ name: "wallet-address", aliases: ["wallet"], required: true },
|
|
4172
|
+
{ name: "object-key" },
|
|
4173
|
+
{ name: "name" },
|
|
4174
|
+
{ name: "latest", bareBoolean: true },
|
|
4175
|
+
{ name: "at" },
|
|
4176
|
+
{ name: "location" },
|
|
4177
|
+
{ name: "region" }
|
|
4178
|
+
]
|
|
4179
|
+
};
|
|
4180
|
+
var opStatusSchema = {
|
|
4181
|
+
args: [
|
|
4182
|
+
{ name: "operation-id", required: true },
|
|
4183
|
+
{ name: "cancel", bareBoolean: true }
|
|
4184
|
+
]
|
|
4185
|
+
};
|
|
4186
|
+
|
|
3764
4187
|
// src/cloud-command.ts
|
|
3765
4188
|
var SUPPORTED_BACKUP_PLATFORMS = /* @__PURE__ */ new Set(["darwin", "linux"]);
|
|
3766
4189
|
var BACKUP_DIR_SUBPATH = join8(".openclaw", "mnemospark", "backup");
|
|
@@ -3774,25 +4197,12 @@ var TAR_OVERHEAD_BYTES = 10 * 1024 * 1024;
|
|
|
3774
4197
|
var QUOTE_VALIDITY_USER_NOTE = "Quotes are valid for one hour. Please run price-storage again if you need a new quote.";
|
|
3775
4198
|
var MNEMOSPARK_SUPPORT_EMAIL = "pluggedin@mnemospark.ai";
|
|
3776
4199
|
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.";
|
|
3777
|
-
var REQUIRED_PRICE_STORAGE = "
|
|
3778
|
-
var REQUIRED_UPLOAD = "
|
|
3779
|
-
var REQUIRED_BACKUP = "<file|directory> and
|
|
3780
|
-
var REQUIRED_PAYMENT_SETTLE = "
|
|
3781
|
-
var
|
|
3782
|
-
var
|
|
3783
|
-
var REQUIRED_LS = "--wallet-address (for one object add --object-key or --name [--latest|--at]; omit both to list the bucket)";
|
|
3784
|
-
var PAYMENT_SETTLE_FLAG_NAMES = /* @__PURE__ */ new Set([
|
|
3785
|
-
"quote-id",
|
|
3786
|
-
"wallet-address",
|
|
3787
|
-
"object-id",
|
|
3788
|
-
"object-key",
|
|
3789
|
-
"storage-price",
|
|
3790
|
-
"renewal"
|
|
3791
|
-
]);
|
|
3792
|
-
var BOOLEAN_SELECTOR_FLAGS = /* @__PURE__ */ new Set(["latest"]);
|
|
3793
|
-
var BOOLEAN_ASYNC_FLAGS = /* @__PURE__ */ new Set(["async"]);
|
|
3794
|
-
var BOOLEAN_OP_STATUS_FLAGS = /* @__PURE__ */ new Set(["cancel"]);
|
|
3795
|
-
var BOOLEAN_SELECTOR_AND_ASYNC_FLAGS = /* @__PURE__ */ new Set(["latest", "async"]);
|
|
4200
|
+
var REQUIRED_PRICE_STORAGE = "wallet-address:, object-id:, object-id-hash:, gb:, provider:, region:";
|
|
4201
|
+
var REQUIRED_UPLOAD = "quote-id:, wallet-address:, object-id:, object-id-hash:";
|
|
4202
|
+
var REQUIRED_BACKUP = "<file|directory> and name:<friendly-name>";
|
|
4203
|
+
var REQUIRED_PAYMENT_SETTLE = "wallet-address: and (quote-id: | renewal:true with object-key:)";
|
|
4204
|
+
var REQUIRED_STORAGE_OBJECT = "wallet-address: and one of (object-key: | name: [latest:true|at:<timestamp>])";
|
|
4205
|
+
var REQUIRED_LS = "wallet-address: (for one object add object-key: or name: [latest:true|at:<timestamp>]; omit both to list the bucket)";
|
|
3796
4206
|
var ORCHESTRATOR_MODES = /* @__PURE__ */ new Set(["inline", "subagent"]);
|
|
3797
4207
|
function expandTilde(path) {
|
|
3798
4208
|
const trimmed = path.trim();
|
|
@@ -3807,63 +4217,66 @@ function expandTilde(path) {
|
|
|
3807
4217
|
var CLOUD_HELP_TEXT = [
|
|
3808
4218
|
"\u2601\uFE0F **mnemospark - Wallet and go.** \u{1F499}",
|
|
3809
4219
|
"",
|
|
4220
|
+
"**Syntax:** use `/mnemospark cloud \u2026`. Prefer `key:value` for arguments; `key=value` and `--key value` are also accepted. Optional verbose markers: `cloud:true`, `price-storage:true`, etc. Aliases: `wallet:` \u2192 wallet-address, `object:` \u2192 object-id, `quote:` \u2192 quote-id, `hash:` \u2192 object-id-hash.",
|
|
4221
|
+
"",
|
|
3810
4222
|
"**Cloud Commands**",
|
|
3811
4223
|
"",
|
|
3812
|
-
"\u2022 `/
|
|
4224
|
+
"\u2022 `/mnemospark cloud` or `/mnemospark cloud help` \u2014 show this message (equivalent: `/mnemospark cloud:true help:true`)",
|
|
3813
4225
|
"",
|
|
3814
|
-
"\u2022 `/
|
|
4226
|
+
"\u2022 `/mnemospark cloud backup <file|directory> name:<friendly-name> [async:true] [orchestrator:<inline|subagent>] [timeout-seconds:<n>]`",
|
|
3815
4227
|
" 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.",
|
|
3816
4228
|
" Required: " + REQUIRED_BACKUP,
|
|
3817
4229
|
"",
|
|
3818
|
-
"\u2022 `/
|
|
3819
|
-
" Purpose: request a storage quote before upload (defaults shown; override
|
|
4230
|
+
"\u2022 `/mnemospark cloud price-storage wallet-address:<addr> object-id:<id> object-id-hash:<hash> gb:<gb> provider:aws region:us-east-1`",
|
|
4231
|
+
" Purpose: request a storage quote before upload (defaults shown; override `provider:` / `region:` for other regions).",
|
|
3820
4232
|
" Required: " + REQUIRED_PRICE_STORAGE,
|
|
4233
|
+
" Shorter: `wallet:\u2026 object:\u2026 hash:\u2026 gb:\u2026 provider:\u2026 region:\u2026`",
|
|
3821
4234
|
"",
|
|
3822
|
-
"\u2022 `/
|
|
4235
|
+
"\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>]`",
|
|
3823
4236
|
" Purpose: upload an encrypted object using a valid quote-id.",
|
|
3824
4237
|
" Required: " + REQUIRED_UPLOAD,
|
|
3825
4238
|
"",
|
|
3826
|
-
"\u2022 `/
|
|
4239
|
+
"\u2022 `/mnemospark cloud payment-settle (quote-id:<quote-id> | renewal:true object-key:<key>) wallet-address:<addr> [object-id:<id>] [storage-price:<n>]`",
|
|
3827
4240
|
" Purpose: settle storage payment before upload (quote) or on the monthly cron (renewal, no new quote). Uses the same proxy + x402 path as upload pre-settlement.",
|
|
3828
4241
|
" Required: " + REQUIRED_PAYMENT_SETTLE + " (wallet private key must match the address).",
|
|
3829
4242
|
"",
|
|
3830
|
-
"\u2022 `/
|
|
4243
|
+
"\u2022 `/mnemospark cloud ls wallet-address:<addr> [object-key:<key> | name:<friendly-name> | omit both to list bucket] [latest:true|at:<timestamp>]`",
|
|
3831
4244
|
" Purpose: stat one object or list all keys in the wallet bucket (S3).",
|
|
3832
4245
|
" Required: " + REQUIRED_LS,
|
|
3833
4246
|
"",
|
|
3834
|
-
"\u2022 `/
|
|
4247
|
+
"\u2022 `/mnemospark cloud download wallet-address:<addr> [object-key:<object-key> | name:<friendly-name>] [latest:true|at:<timestamp>] [async:true] [orchestrator:<inline|subagent>] [timeout-seconds:<n>]`",
|
|
3835
4248
|
" Purpose: fetch an object to local disk.",
|
|
3836
4249
|
" Required: " + REQUIRED_STORAGE_OBJECT,
|
|
3837
4250
|
"",
|
|
3838
|
-
"\u2022 `/
|
|
4251
|
+
"\u2022 `/mnemospark cloud delete wallet-address:<addr> [object-key:<object-key> | name:<friendly-name>] [latest:true|at:<timestamp>]`",
|
|
3839
4252
|
" Purpose: remove a remote object and local cron tracking when present.",
|
|
3840
4253
|
" Required: " + REQUIRED_STORAGE_OBJECT,
|
|
3841
4254
|
"",
|
|
3842
|
-
"\u2022 `/
|
|
4255
|
+
"\u2022 `/mnemospark cloud op-status operation-id:<id> [cancel:true]`",
|
|
3843
4256
|
" Purpose: inspect async operation status, or request cancellation for subagent runs.",
|
|
3844
|
-
" Required:
|
|
4257
|
+
" Required: operation-id:<id>",
|
|
3845
4258
|
"",
|
|
3846
4259
|
"Async orchestration flags (`backup`, `upload`, `download` only):",
|
|
3847
|
-
"\u2022
|
|
4260
|
+
"\u2022 `async:true`",
|
|
3848
4261
|
" Start operation in background and return quickly with operation-id.",
|
|
3849
|
-
"\u2022
|
|
4262
|
+
"\u2022 `orchestrator:<inline|subagent>`",
|
|
3850
4263
|
" Choose async engine. Default when omitted is `inline`.",
|
|
3851
4264
|
" Use `subagent` for explicit subagent session tracking and cancellation.",
|
|
3852
|
-
"\u2022
|
|
3853
|
-
" Optional per-operation timeout. Valid only with
|
|
4265
|
+
"\u2022 `timeout-seconds:<n>`",
|
|
4266
|
+
" Optional per-operation timeout. Valid only with `async:true` and `orchestrator:subagent`.",
|
|
3854
4267
|
" `n` must be a positive integer (seconds).",
|
|
3855
|
-
"\u2022 `op-status
|
|
4268
|
+
"\u2022 `op-status` with `cancel:true`",
|
|
3856
4269
|
" Cancel a subagent-orchestrated operation by operation-id (idempotent).",
|
|
3857
4270
|
"",
|
|
3858
4271
|
"Examples:",
|
|
3859
|
-
"\u2022 `/
|
|
3860
|
-
"\u2022 `/
|
|
3861
|
-
"\u2022 `/
|
|
3862
|
-
"\u2022 `/
|
|
4272
|
+
"\u2022 `/mnemospark cloud upload ... async:true orchestrator:subagent`",
|
|
4273
|
+
"\u2022 `/mnemospark cloud download ... async:true orchestrator:subagent timeout-seconds:900`",
|
|
4274
|
+
"\u2022 `/mnemospark cloud op-status operation-id:<id>`",
|
|
4275
|
+
"\u2022 `/mnemospark cloud op-status operation-id:<id> cancel:true`",
|
|
3863
4276
|
"",
|
|
3864
4277
|
CLOUD_HELP_FOOTER_STATE,
|
|
3865
4278
|
"",
|
|
3866
|
-
"Backup uses your configured mnemospark wallet key (no
|
|
4279
|
+
"Backup uses your configured mnemospark wallet key (no `wallet-address:` argument). Commands price-storage, upload, ls, download, delete, and payment-settle require `wallet-address:<addr>` (or `wallet:<addr>`) on the command line (must match that wallet)."
|
|
3867
4280
|
].join("\n");
|
|
3868
4281
|
var UnsupportedBackupPlatformError = class extends Error {
|
|
3869
4282
|
constructor(platform) {
|
|
@@ -3892,37 +4305,6 @@ function tokenizeArgsRaw(input) {
|
|
|
3892
4305
|
}
|
|
3893
4306
|
return tokens;
|
|
3894
4307
|
}
|
|
3895
|
-
function tokenizeArgs(input) {
|
|
3896
|
-
return tokenizeArgsRaw(input).map((token) => stripWrappingQuotes(token));
|
|
3897
|
-
}
|
|
3898
|
-
function parseNamedFlagsTokens(tokens, booleanFlags = /* @__PURE__ */ new Set()) {
|
|
3899
|
-
if (tokens.length === 0) {
|
|
3900
|
-
return null;
|
|
3901
|
-
}
|
|
3902
|
-
const parsed = {};
|
|
3903
|
-
for (let i = 0; i < tokens.length; i += 1) {
|
|
3904
|
-
const keyToken = tokens[i];
|
|
3905
|
-
if (!keyToken.startsWith("--")) {
|
|
3906
|
-
return null;
|
|
3907
|
-
}
|
|
3908
|
-
const key = keyToken.slice(2).toLowerCase().replace(/_/g, "-");
|
|
3909
|
-
const value = tokens[i + 1];
|
|
3910
|
-
if (!value || value.startsWith("--")) {
|
|
3911
|
-
if (booleanFlags.has(key)) {
|
|
3912
|
-
parsed[key] = "true";
|
|
3913
|
-
continue;
|
|
3914
|
-
}
|
|
3915
|
-
return null;
|
|
3916
|
-
}
|
|
3917
|
-
parsed[key] = value;
|
|
3918
|
-
i += 1;
|
|
3919
|
-
}
|
|
3920
|
-
return parsed;
|
|
3921
|
-
}
|
|
3922
|
-
function parseNamedFlags(input, booleanFlags = /* @__PURE__ */ new Set()) {
|
|
3923
|
-
const tokens = tokenizeArgs(input);
|
|
3924
|
-
return parseNamedFlagsTokens(tokens, booleanFlags);
|
|
3925
|
-
}
|
|
3926
4308
|
function parseObjectSelector(flags) {
|
|
3927
4309
|
const objectKey = flags["object-key"]?.trim();
|
|
3928
4310
|
const name = flags.name?.trim();
|
|
@@ -4015,10 +4397,18 @@ function parseAsyncOperationArgs(flags) {
|
|
|
4015
4397
|
timeoutSeconds: parsedTimeoutSeconds === void 0 ? void 0 : parsedTimeoutSeconds
|
|
4016
4398
|
};
|
|
4017
4399
|
}
|
|
4018
|
-
var INVALID_ASYNC_FLAGS_MESSAGE = "invalid async flags.
|
|
4400
|
+
var INVALID_ASYNC_FLAGS_MESSAGE = "invalid async flags. `orchestrator:` and `timeout-seconds:` require `async:true`, and `timeout-seconds:` is only valid with `orchestrator:subagent`.";
|
|
4019
4401
|
function stripAsyncControlFlags(args) {
|
|
4020
4402
|
const tokens = tokenizeArgsRaw(args ?? "");
|
|
4021
4403
|
const filtered = [];
|
|
4404
|
+
const isAsyncControlKey = (rawKey) => {
|
|
4405
|
+
const canonical = rawKey.trim().toLowerCase().replace(/_/g, "-");
|
|
4406
|
+
return canonical === "async" || canonical === "orchestrator" || canonical === "timeout-seconds";
|
|
4407
|
+
};
|
|
4408
|
+
const isBareBooleanFlag = (rawToken) => {
|
|
4409
|
+
const canonical = rawToken.trim().toLowerCase().replace(/^--/, "").replace(/_/g, "-");
|
|
4410
|
+
return canonical === "async" || canonical === "latest";
|
|
4411
|
+
};
|
|
4022
4412
|
for (let idx = 0; idx < tokens.length; idx += 1) {
|
|
4023
4413
|
const token = tokens[idx];
|
|
4024
4414
|
const lowerToken = token.toLowerCase();
|
|
@@ -4029,35 +4419,71 @@ function stripAsyncControlFlags(args) {
|
|
|
4029
4419
|
idx += 1;
|
|
4030
4420
|
continue;
|
|
4031
4421
|
}
|
|
4422
|
+
const previousToken = tokens[idx - 1];
|
|
4423
|
+
if (previousToken && previousToken.startsWith("--") && !isBareBooleanFlag(previousToken)) {
|
|
4424
|
+
filtered.push(token);
|
|
4425
|
+
continue;
|
|
4426
|
+
}
|
|
4427
|
+
const unwrapped = stripWrappingQuotes(token);
|
|
4428
|
+
const colonIdx = unwrapped.indexOf(":");
|
|
4429
|
+
const equalsIdx = unwrapped.indexOf("=");
|
|
4430
|
+
const splitIdx = colonIdx > 0 && equalsIdx > 0 ? Math.min(colonIdx, equalsIdx) : Math.max(colonIdx, equalsIdx);
|
|
4431
|
+
if (splitIdx > 0) {
|
|
4432
|
+
const candidateKey = unwrapped.slice(0, splitIdx);
|
|
4433
|
+
if (/^[A-Za-z_][A-Za-z0-9_-]*$/.test(candidateKey) && isAsyncControlKey(candidateKey)) {
|
|
4434
|
+
continue;
|
|
4435
|
+
}
|
|
4436
|
+
}
|
|
4032
4437
|
filtered.push(token);
|
|
4033
4438
|
}
|
|
4034
4439
|
return filtered.join(" ");
|
|
4035
4440
|
}
|
|
4441
|
+
function mergeArgParseWarnings(a, b) {
|
|
4442
|
+
return [...a, ...b];
|
|
4443
|
+
}
|
|
4036
4444
|
function parseCloudArgs(args) {
|
|
4037
4445
|
const trimmed = args?.trim() ?? "";
|
|
4038
4446
|
if (!trimmed) {
|
|
4039
4447
|
return { mode: "help" };
|
|
4040
4448
|
}
|
|
4041
|
-
const
|
|
4042
|
-
const
|
|
4043
|
-
const
|
|
4449
|
+
const norm = normalizeInputForParsing(trimmed);
|
|
4450
|
+
const text = norm.text;
|
|
4451
|
+
const normWarnings = norm.warnings;
|
|
4452
|
+
const spaceIdx = text.search(/\s/);
|
|
4453
|
+
const rawFirst = spaceIdx === -1 ? text : text.slice(0, spaceIdx);
|
|
4454
|
+
const rest = spaceIdx === -1 ? "" : text.slice(spaceIdx + 1).trim();
|
|
4455
|
+
const subParsed = parseVerboseToken(rawFirst);
|
|
4456
|
+
if (!subParsed.ok) {
|
|
4457
|
+
return {
|
|
4458
|
+
mode: "arg-parse-failure",
|
|
4459
|
+
errors: [`Invalid subcommand token "${rawFirst}". Use name:true only with value true.`],
|
|
4460
|
+
warnings: normWarnings
|
|
4461
|
+
};
|
|
4462
|
+
}
|
|
4463
|
+
const subcommand = subParsed.name;
|
|
4044
4464
|
if (subcommand === "help") {
|
|
4045
4465
|
return { mode: "help" };
|
|
4046
4466
|
}
|
|
4047
4467
|
if (subcommand === "backup") {
|
|
4048
|
-
const tokens =
|
|
4468
|
+
const tokens = tokenizeArgsRaw(rest);
|
|
4049
4469
|
if (tokens.length === 0) {
|
|
4050
4470
|
return { mode: "unknown" };
|
|
4051
4471
|
}
|
|
4052
|
-
const backupTarget = tokens[0] ?? "";
|
|
4472
|
+
const backupTarget = stripWrappingQuotes(tokens[0] ?? "");
|
|
4053
4473
|
if (!backupTarget) {
|
|
4054
4474
|
return { mode: "unknown" };
|
|
4055
4475
|
}
|
|
4056
4476
|
const remainingTokens = tokens.slice(1);
|
|
4057
|
-
const
|
|
4058
|
-
|
|
4059
|
-
|
|
4477
|
+
const flagsPart = remainingTokens.join(" ");
|
|
4478
|
+
const parsed = parseCommandArgs(flagsPart, backupFlagsSchema);
|
|
4479
|
+
if (!parsed.ok) {
|
|
4480
|
+
return {
|
|
4481
|
+
mode: "arg-parse-failure",
|
|
4482
|
+
errors: parsed.errors,
|
|
4483
|
+
warnings: mergeArgParseWarnings(normWarnings, parsed.warnings)
|
|
4484
|
+
};
|
|
4060
4485
|
}
|
|
4486
|
+
const flags = valuesToStringRecord(parsed.values);
|
|
4061
4487
|
const asyncArgs = parseAsyncOperationArgs(flags);
|
|
4062
4488
|
if (!asyncArgs) {
|
|
4063
4489
|
return { mode: "backup-invalid-async" };
|
|
@@ -4074,10 +4500,15 @@ function parseCloudArgs(args) {
|
|
|
4074
4500
|
};
|
|
4075
4501
|
}
|
|
4076
4502
|
if (subcommand === "price-storage") {
|
|
4077
|
-
const
|
|
4078
|
-
if (!
|
|
4079
|
-
return {
|
|
4503
|
+
const parsed = parseCommandArgs(rest, priceStorageSchema);
|
|
4504
|
+
if (!parsed.ok) {
|
|
4505
|
+
return {
|
|
4506
|
+
mode: "arg-parse-failure",
|
|
4507
|
+
errors: parsed.errors,
|
|
4508
|
+
warnings: mergeArgParseWarnings(normWarnings, parsed.warnings)
|
|
4509
|
+
};
|
|
4080
4510
|
}
|
|
4511
|
+
const flags = valuesToStringRecord(parsed.values);
|
|
4081
4512
|
const gb = Number.parseFloat(flags.gb ?? "");
|
|
4082
4513
|
const request = parsePriceStorageQuoteRequest({
|
|
4083
4514
|
wallet_address: flags["wallet-address"],
|
|
@@ -4093,10 +4524,15 @@ function parseCloudArgs(args) {
|
|
|
4093
4524
|
return { mode: "price-storage", priceStorageRequest: request };
|
|
4094
4525
|
}
|
|
4095
4526
|
if (subcommand === "upload") {
|
|
4096
|
-
const
|
|
4097
|
-
if (!
|
|
4098
|
-
return {
|
|
4527
|
+
const parsed = parseCommandArgs(rest, uploadSchema);
|
|
4528
|
+
if (!parsed.ok) {
|
|
4529
|
+
return {
|
|
4530
|
+
mode: "arg-parse-failure",
|
|
4531
|
+
errors: parsed.errors,
|
|
4532
|
+
warnings: mergeArgParseWarnings(normWarnings, parsed.warnings)
|
|
4533
|
+
};
|
|
4099
4534
|
}
|
|
4535
|
+
const flags = valuesToStringRecord(parsed.values);
|
|
4100
4536
|
const asyncArgs = parseAsyncOperationArgs(flags);
|
|
4101
4537
|
if (!asyncArgs) {
|
|
4102
4538
|
return { mode: "upload-invalid-async" };
|
|
@@ -4121,15 +4557,15 @@ function parseCloudArgs(args) {
|
|
|
4121
4557
|
};
|
|
4122
4558
|
}
|
|
4123
4559
|
if (subcommand === "payment-settle") {
|
|
4124
|
-
const
|
|
4125
|
-
if (!
|
|
4126
|
-
return {
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
}
|
|
4560
|
+
const parsed = parseCommandArgs(rest, paymentSettleSchema);
|
|
4561
|
+
if (!parsed.ok) {
|
|
4562
|
+
return {
|
|
4563
|
+
mode: "arg-parse-failure",
|
|
4564
|
+
errors: parsed.errors,
|
|
4565
|
+
warnings: mergeArgParseWarnings(normWarnings, parsed.warnings)
|
|
4566
|
+
};
|
|
4132
4567
|
}
|
|
4568
|
+
const flags = valuesToStringRecord(parsed.values);
|
|
4133
4569
|
const walletAddress = flags["wallet-address"]?.trim();
|
|
4134
4570
|
if (!walletAddress) {
|
|
4135
4571
|
return { mode: "payment-settle-invalid" };
|
|
@@ -4169,11 +4605,16 @@ function parseCloudArgs(args) {
|
|
|
4169
4605
|
};
|
|
4170
4606
|
}
|
|
4171
4607
|
if (subcommand === "ls") {
|
|
4172
|
-
const
|
|
4173
|
-
if (!
|
|
4174
|
-
return {
|
|
4608
|
+
const parsed = parseCommandArgs(rest, lsSchema);
|
|
4609
|
+
if (!parsed.ok) {
|
|
4610
|
+
return {
|
|
4611
|
+
mode: "arg-parse-failure",
|
|
4612
|
+
errors: parsed.errors,
|
|
4613
|
+
warnings: mergeArgParseWarnings(normWarnings, parsed.warnings)
|
|
4614
|
+
};
|
|
4175
4615
|
}
|
|
4176
|
-
const
|
|
4616
|
+
const flags = valuesToStringRecord(parsed.values);
|
|
4617
|
+
const walletAddress = flags["wallet-address"]?.trim() ?? "";
|
|
4177
4618
|
if (!walletAddress) {
|
|
4178
4619
|
return { mode: "ls-invalid" };
|
|
4179
4620
|
}
|
|
@@ -4205,10 +4646,15 @@ function parseCloudArgs(args) {
|
|
|
4205
4646
|
};
|
|
4206
4647
|
}
|
|
4207
4648
|
if (subcommand === "download") {
|
|
4208
|
-
const
|
|
4209
|
-
if (!
|
|
4210
|
-
return {
|
|
4649
|
+
const parsed = parseCommandArgs(rest, downloadSchema);
|
|
4650
|
+
if (!parsed.ok) {
|
|
4651
|
+
return {
|
|
4652
|
+
mode: "arg-parse-failure",
|
|
4653
|
+
errors: parsed.errors,
|
|
4654
|
+
warnings: mergeArgParseWarnings(normWarnings, parsed.warnings)
|
|
4655
|
+
};
|
|
4211
4656
|
}
|
|
4657
|
+
const flags = valuesToStringRecord(parsed.values);
|
|
4212
4658
|
const asyncArgs = parseAsyncOperationArgs(flags);
|
|
4213
4659
|
if (!asyncArgs) {
|
|
4214
4660
|
return { mode: "download-invalid-async" };
|
|
@@ -4229,10 +4675,15 @@ function parseCloudArgs(args) {
|
|
|
4229
4675
|
};
|
|
4230
4676
|
}
|
|
4231
4677
|
if (subcommand === "delete") {
|
|
4232
|
-
const
|
|
4233
|
-
if (!
|
|
4234
|
-
return {
|
|
4678
|
+
const parsed = parseCommandArgs(rest, deleteSchema);
|
|
4679
|
+
if (!parsed.ok) {
|
|
4680
|
+
return {
|
|
4681
|
+
mode: "arg-parse-failure",
|
|
4682
|
+
errors: parsed.errors,
|
|
4683
|
+
warnings: mergeArgParseWarnings(normWarnings, parsed.warnings)
|
|
4684
|
+
};
|
|
4235
4685
|
}
|
|
4686
|
+
const flags = valuesToStringRecord(parsed.values);
|
|
4236
4687
|
const selector = parseObjectSelector(flags);
|
|
4237
4688
|
if (!selector) {
|
|
4238
4689
|
return { mode: "delete-invalid" };
|
|
@@ -4244,12 +4695,20 @@ function parseCloudArgs(args) {
|
|
|
4244
4695
|
return { mode: "delete", storageObjectRequest: request, nameSelector: selector.nameSelector };
|
|
4245
4696
|
}
|
|
4246
4697
|
if (subcommand === "op-status") {
|
|
4247
|
-
const
|
|
4248
|
-
|
|
4698
|
+
const parsed = parseCommandArgs(rest, opStatusSchema);
|
|
4699
|
+
if (!parsed.ok) {
|
|
4700
|
+
return {
|
|
4701
|
+
mode: "arg-parse-failure",
|
|
4702
|
+
errors: parsed.errors,
|
|
4703
|
+
warnings: mergeArgParseWarnings(normWarnings, parsed.warnings)
|
|
4704
|
+
};
|
|
4705
|
+
}
|
|
4706
|
+
const flags = valuesToStringRecord(parsed.values);
|
|
4707
|
+
const operationId = flags["operation-id"]?.trim();
|
|
4249
4708
|
if (!operationId) {
|
|
4250
4709
|
return { mode: "op-status-invalid" };
|
|
4251
4710
|
}
|
|
4252
|
-
return { mode: "op-status", operationId, cancel: flags
|
|
4711
|
+
return { mode: "op-status", operationId, cancel: flags.cancel === "true" };
|
|
4253
4712
|
}
|
|
4254
4713
|
return { mode: "unknown" };
|
|
4255
4714
|
}
|
|
@@ -4334,7 +4793,7 @@ async function resolveLocalUploadArchivePath(backupDir, objectId, friendlyName)
|
|
|
4334
4793
|
} catch {
|
|
4335
4794
|
return {
|
|
4336
4795
|
ok: false,
|
|
4337
|
-
message: `Cannot upload storage object: local archive not found. Run /
|
|
4796
|
+
message: `Cannot upload storage object: local archive not found. Run /mnemospark cloud backup with name:<friendly-name> (canonical layout) or restore the legacy file at ${legacyPath}.`
|
|
4338
4797
|
};
|
|
4339
4798
|
}
|
|
4340
4799
|
}
|
|
@@ -4555,7 +5014,7 @@ function buildStoragePaymentRenewalArgs(job) {
|
|
|
4555
5014
|
].join(" ");
|
|
4556
5015
|
}
|
|
4557
5016
|
function buildStoragePaymentCronCommand(job) {
|
|
4558
|
-
return `/
|
|
5017
|
+
return `/mnemospark cloud ${buildStoragePaymentRenewalArgs(job)}`;
|
|
4559
5018
|
}
|
|
4560
5019
|
function buildOpenClawRenewalAgentMessage(openClawHome, renewalArgs) {
|
|
4561
5020
|
const cliPath = join8(openClawHome, ".openclaw/extensions/mnemospark/dist/cli.js");
|
|
@@ -4895,7 +5354,7 @@ async function maybeCleanupLocalBackupArchive(archivePath) {
|
|
|
4895
5354
|
}
|
|
4896
5355
|
}
|
|
4897
5356
|
function formatStorageUploadUserMessage(upload, cronJobId) {
|
|
4898
|
-
const lsLine = `/
|
|
5357
|
+
const lsLine = `/mnemospark cloud ls wallet-address:\`${upload.addr}\``;
|
|
4899
5358
|
return [
|
|
4900
5359
|
`Your file \`${upload.object_id}\` with key \`${upload.object_key}\` has been stored using \`${upload.provider}\` in folder \`${upload.bucket_name}\` in region \`${upload.location}\``,
|
|
4901
5360
|
"",
|
|
@@ -4953,7 +5412,7 @@ function extractLsErrorMessage(error) {
|
|
|
4953
5412
|
return null;
|
|
4954
5413
|
}
|
|
4955
5414
|
function formatPriceStorageUserMessage(quote, localArchiveHint) {
|
|
4956
|
-
const uploadLine = `/
|
|
5415
|
+
const uploadLine = `/mnemospark cloud upload quote-id:\`${quote.quote_id}\` wallet-address:\`${quote.addr}\` object-id:\`${quote.object_id}\` object-id-hash:\`${quote.object_id_hash}\``;
|
|
4957
5416
|
const lines = [
|
|
4958
5417
|
`Your storage quote \`${quote.quote_id}\`: storage price \`$${quote.storage_price}\` for file \`${quote.object_id}\` with file size \`${quote.object_size_gb}\` in \`${quote.provider}\` \`${quote.location}\`.`,
|
|
4959
5418
|
"",
|
|
@@ -4978,7 +5437,7 @@ var DEFAULT_BACKUP_QUOTE_PROVIDER = "aws";
|
|
|
4978
5437
|
var DEFAULT_BACKUP_QUOTE_REGION = "us-east-1";
|
|
4979
5438
|
function formatBackupSuccessUserMessage(result, walletAddress, friendlyName) {
|
|
4980
5439
|
const hash = result.objectIdHash.replace(/\s/g, "");
|
|
4981
|
-
const priceStorageLine = `/
|
|
5440
|
+
const priceStorageLine = `/mnemospark cloud price-storage wallet-address:\`${walletAddress}\` object-id:\`${result.objectId}\` object-id-hash:\`${hash}\` gb:\`${result.objectSizeGb}\` provider:${DEFAULT_BACKUP_QUOTE_PROVIDER} region:${DEFAULT_BACKUP_QUOTE_REGION}`;
|
|
4982
5441
|
return [
|
|
4983
5442
|
`Backup archive: \`${result.archivePath}\``,
|
|
4984
5443
|
"",
|
|
@@ -4994,10 +5453,10 @@ function formatBackupSuccessUserMessage(result, walletAddress, friendlyName) {
|
|
|
4994
5453
|
`The default region is ${DEFAULT_BACKUP_QUOTE_REGION}. Change the command parameters to switch regions (not required).`,
|
|
4995
5454
|
"",
|
|
4996
5455
|
"Region examples (merge into the command above):",
|
|
4997
|
-
"North America:
|
|
4998
|
-
"Europe:
|
|
4999
|
-
"South America:
|
|
5000
|
-
"Asia Pacific:
|
|
5456
|
+
"North America: `provider:aws region:us-east-1`",
|
|
5457
|
+
"Europe: `provider:aws region:eu-north-1`",
|
|
5458
|
+
"South America: `provider:aws region:sa-east-1`",
|
|
5459
|
+
"Asia Pacific: `provider:aws region:ap-northeast-1`"
|
|
5001
5460
|
].join("\n");
|
|
5002
5461
|
}
|
|
5003
5462
|
function createInProcessSubagentOrchestrator() {
|
|
@@ -5101,9 +5560,9 @@ function createInProcessSubagentOrchestrator() {
|
|
|
5101
5560
|
function createCloudCommand(options = {}) {
|
|
5102
5561
|
const subagentOrchestrator = options.subagentOrchestrator ?? createInProcessSubagentOrchestrator();
|
|
5103
5562
|
return {
|
|
5104
|
-
name: "
|
|
5563
|
+
name: "mnemospark",
|
|
5105
5564
|
nativeNames: {
|
|
5106
|
-
default: "
|
|
5565
|
+
default: "mnemospark"
|
|
5107
5566
|
},
|
|
5108
5567
|
description: "Manage mnemospark cloud storage workflow commands",
|
|
5109
5568
|
acceptsArgs: true,
|
|
@@ -5431,15 +5890,24 @@ async function runCloudCommandHandler(ctx, options, executionContext = {}) {
|
|
|
5431
5890
|
isError: parsed.mode === "unknown"
|
|
5432
5891
|
};
|
|
5433
5892
|
}
|
|
5434
|
-
if (parsed.mode === "
|
|
5893
|
+
if (parsed.mode === "arg-parse-failure") {
|
|
5435
5894
|
return {
|
|
5436
|
-
text:
|
|
5895
|
+
text: [
|
|
5896
|
+
"Could not parse command arguments.",
|
|
5897
|
+
...parsed.errors.map((e) => `- ${e}`),
|
|
5898
|
+
...parsed.warnings.length > 0 ? ["", "Notes:", ...parsed.warnings.map((w) => `- ${w}`)] : [],
|
|
5899
|
+
"",
|
|
5900
|
+
"Accepted formats:",
|
|
5901
|
+
"- key:value",
|
|
5902
|
+
"- key=value",
|
|
5903
|
+
"- --key value"
|
|
5904
|
+
].join("\n"),
|
|
5437
5905
|
isError: true
|
|
5438
5906
|
};
|
|
5439
5907
|
}
|
|
5440
|
-
if (parsed.mode === "
|
|
5908
|
+
if (parsed.mode === "price-storage-invalid") {
|
|
5441
5909
|
return {
|
|
5442
|
-
text:
|
|
5910
|
+
text: `Cannot price storage: required arguments are ${REQUIRED_PRICE_STORAGE}.`,
|
|
5443
5911
|
isError: true
|
|
5444
5912
|
};
|
|
5445
5913
|
}
|
|
@@ -5469,7 +5937,7 @@ async function runCloudCommandHandler(ctx, options, executionContext = {}) {
|
|
|
5469
5937
|
}
|
|
5470
5938
|
if (parsed.mode === "payment-settle-invalid") {
|
|
5471
5939
|
return {
|
|
5472
|
-
text: `Cannot settle payment: required arguments are ${REQUIRED_PAYMENT_SETTLE}. Optional:
|
|
5940
|
+
text: `Cannot settle payment: required arguments are ${REQUIRED_PAYMENT_SETTLE}. Optional: object-id:, storage-price:.`,
|
|
5473
5941
|
isError: true
|
|
5474
5942
|
};
|
|
5475
5943
|
}
|
|
@@ -5499,7 +5967,7 @@ async function runCloudCommandHandler(ctx, options, executionContext = {}) {
|
|
|
5499
5967
|
}
|
|
5500
5968
|
if (parsed.mode === "op-status-invalid") {
|
|
5501
5969
|
return {
|
|
5502
|
-
text: "Cannot get operation status: required arguments are
|
|
5970
|
+
text: "Cannot get operation status: required arguments are operation-id:<id>.",
|
|
5503
5971
|
isError: true
|
|
5504
5972
|
};
|
|
5505
5973
|
}
|
|
@@ -5635,7 +6103,7 @@ ${operation.result_text}` : meta;
|
|
|
5635
6103
|
const walletAccount = privateKeyToAccount5(walletKey);
|
|
5636
6104
|
if (walletAccount.address.toLowerCase() !== req.wallet_address.toLowerCase()) {
|
|
5637
6105
|
return {
|
|
5638
|
-
text: `Cannot settle payment: wallet key address ${walletAccount.address} does not match
|
|
6106
|
+
text: `Cannot settle payment: wallet key address ${walletAccount.address} does not match wallet-address: ${req.wallet_address}.`,
|
|
5639
6107
|
isError: true
|
|
5640
6108
|
};
|
|
5641
6109
|
}
|
|
@@ -5729,7 +6197,7 @@ ${operation.result_text}` : meta;
|
|
|
5729
6197
|
});
|
|
5730
6198
|
const label = req.renewal ? `object ${req.object_key}` : `quote ${req.quote_id}`;
|
|
5731
6199
|
return {
|
|
5732
|
-
text: transId ? `Payment settled for ${label} (
|
|
6200
|
+
text: transId ? `Payment settled for ${label} (trans-id: ${transId}).` : `Payment settled for ${label}.`
|
|
5733
6201
|
};
|
|
5734
6202
|
}
|
|
5735
6203
|
await datastore.upsertPayment({
|
|
@@ -5808,7 +6276,7 @@ ${operation.result_text}` : meta;
|
|
|
5808
6276
|
args: syncArgs,
|
|
5809
6277
|
timeoutSeconds: parsed.timeoutSeconds,
|
|
5810
6278
|
requestedBy: {
|
|
5811
|
-
pluginCommand: "
|
|
6279
|
+
pluginCommand: "mnemospark",
|
|
5812
6280
|
chatId: ctx.channel,
|
|
5813
6281
|
senderId: ctx.senderId
|
|
5814
6282
|
}
|
|
@@ -5991,7 +6459,7 @@ ${operation.result_text}` : meta;
|
|
|
5991
6459
|
`orchestrator: subagent`,
|
|
5992
6460
|
`subagent-session-id: ${dispatchResult.sessionId}`,
|
|
5993
6461
|
timeoutSeconds ? `timeout-seconds: ${timeoutSeconds}` : null,
|
|
5994
|
-
`Use /
|
|
6462
|
+
`Use /mnemospark cloud op-status operation-id:${operationId}`
|
|
5995
6463
|
].filter((line) => Boolean(line)).join("\n")
|
|
5996
6464
|
};
|
|
5997
6465
|
} catch (dispatchError) {
|
|
@@ -6094,7 +6562,7 @@ operation-id: ${operationId}`,
|
|
|
6094
6562
|
text: [
|
|
6095
6563
|
`Operation started in background. operation-id: ${operationId}`,
|
|
6096
6564
|
`orchestrator: inline`,
|
|
6097
|
-
`Use /
|
|
6565
|
+
`Use /mnemospark cloud op-status operation-id:${operationId}`
|
|
6098
6566
|
].join("\n")
|
|
6099
6567
|
};
|
|
6100
6568
|
}
|
|
@@ -6264,7 +6732,7 @@ operation-id: ${operationId}`,
|
|
|
6264
6732
|
const loggedQuote = await datastore.findQuoteById(parsed.uploadRequest.quote_id);
|
|
6265
6733
|
if (!loggedQuote) {
|
|
6266
6734
|
return {
|
|
6267
|
-
text: "Cannot upload storage object: quote-id not found in local SQLite. Run /
|
|
6735
|
+
text: "Cannot upload storage object: quote-id not found in local SQLite. Run /mnemospark cloud price-storage first (quotes expire after about one hour on the server).",
|
|
6268
6736
|
isError: true
|
|
6269
6737
|
};
|
|
6270
6738
|
}
|
|
@@ -6280,7 +6748,7 @@ operation-id: ${operationId}`,
|
|
|
6280
6748
|
);
|
|
6281
6749
|
if (!dbFriendly?.trim()) {
|
|
6282
6750
|
return {
|
|
6283
|
-
text: "Cannot upload storage object: no friendly name in local SQLite for this object-id. Run /
|
|
6751
|
+
text: "Cannot upload storage object: no friendly name in local SQLite for this object-id. Run /mnemospark cloud backup with --name first.",
|
|
6284
6752
|
isError: true
|
|
6285
6753
|
};
|
|
6286
6754
|
}
|
|
@@ -6306,7 +6774,7 @@ operation-id: ${operationId}`,
|
|
|
6306
6774
|
archiveStats = await stat2(archivePath);
|
|
6307
6775
|
} catch {
|
|
6308
6776
|
return {
|
|
6309
|
-
text: `Cannot upload storage object: local archive not found at ${archivePath}. Run /
|
|
6777
|
+
text: `Cannot upload storage object: local archive not found at ${archivePath}. Run /mnemospark cloud backup first.`,
|
|
6310
6778
|
isError: true
|
|
6311
6779
|
};
|
|
6312
6780
|
}
|
|
@@ -6327,7 +6795,7 @@ operation-id: ${operationId}`,
|
|
|
6327
6795
|
const walletAccount = privateKeyToAccount5(walletKey);
|
|
6328
6796
|
if (walletAccount.address.toLowerCase() !== parsed.uploadRequest.wallet_address.toLowerCase()) {
|
|
6329
6797
|
return {
|
|
6330
|
-
text: `Cannot upload storage object: wallet key address ${walletAccount.address} does not match
|
|
6798
|
+
text: `Cannot upload storage object: wallet key address ${walletAccount.address} does not match wallet-address: ${parsed.uploadRequest.wallet_address}.`,
|
|
6331
6799
|
isError: true
|
|
6332
6800
|
};
|
|
6333
6801
|
}
|
|
@@ -6833,12 +7301,192 @@ operation-id: ${operationId}`,
|
|
|
6833
7301
|
};
|
|
6834
7302
|
}
|
|
6835
7303
|
|
|
7304
|
+
// src/mnemospark-handler.ts
|
|
7305
|
+
var MNEMOSPARK_ROOT_HELP_TEXT = [
|
|
7306
|
+
"\u2601\uFE0F **mnemospark - Wallet and go.** \u{1F499}",
|
|
7307
|
+
"",
|
|
7308
|
+
"**Syntax:** `/mnemospark cloud \u2026` or `/mnemospark wallet \u2026`",
|
|
7309
|
+
"Arguments may use `key:value`, `key=value`, or `--key value`. Optional verbose markers: `cloud:true`, `price-storage:true`, etc. (same as bare words).",
|
|
7310
|
+
"Aliases include `wallet:` \u2192 wallet-address, `object:` \u2192 object-id, `quote:` \u2192 quote-id (see `/mnemospark cloud help`).",
|
|
7311
|
+
"",
|
|
7312
|
+
"**Cloud storage** \u2014 full reference:",
|
|
7313
|
+
"\u2022 `/mnemospark cloud help`",
|
|
7314
|
+
"",
|
|
7315
|
+
"**Wallet** \u2014 status:",
|
|
7316
|
+
"\u2022 `/mnemospark wallet`",
|
|
7317
|
+
"\u2022 `/mnemospark wallet help` \u2014 commands and funding link"
|
|
7318
|
+
].join("\n");
|
|
7319
|
+
var MNEMOSPARK_WALLET_HELP_TEXT = (address) => [
|
|
7320
|
+
"\u2601\uFE0F **mnemospark Wallet**",
|
|
7321
|
+
"",
|
|
7322
|
+
"**Commands:**",
|
|
7323
|
+
"\u2022 `/mnemospark wallet` \u2014 Show address, balance, and key file path",
|
|
7324
|
+
"\u2022 `/mnemospark wallet help` \u2014 This message",
|
|
7325
|
+
"\u2022 `/mnemospark wallet export` \u2014 Export private key for backup (sensitive)",
|
|
7326
|
+
"",
|
|
7327
|
+
`**Fund with USDC on Base:** https://basescan.org/address/${address}`
|
|
7328
|
+
].join("\n");
|
|
7329
|
+
var defaultCloudCommandHandler;
|
|
7330
|
+
function getDefaultCloudCommandHandler() {
|
|
7331
|
+
defaultCloudCommandHandler ??= createCloudCommand().handler;
|
|
7332
|
+
return defaultCloudCommandHandler;
|
|
7333
|
+
}
|
|
7334
|
+
var NO_WALLET_FOUND_TEXT = "No mnemospark wallet found. Run `openclaw plugins install mnemospark`.";
|
|
7335
|
+
function resolveWalletFileSync() {
|
|
7336
|
+
try {
|
|
7337
|
+
if (!existsSync(WALLET_FILE)) {
|
|
7338
|
+
return null;
|
|
7339
|
+
}
|
|
7340
|
+
const walletKey = readFileSync(WALLET_FILE, "utf-8").trim();
|
|
7341
|
+
if (!walletKey.startsWith("0x") || walletKey.length !== 66) {
|
|
7342
|
+
return null;
|
|
7343
|
+
}
|
|
7344
|
+
const account = privateKeyToAccount6(walletKey);
|
|
7345
|
+
const address = account.address.replace(/\s/g, "");
|
|
7346
|
+
if (!address) {
|
|
7347
|
+
return null;
|
|
7348
|
+
}
|
|
7349
|
+
return { walletKey, address };
|
|
7350
|
+
} catch {
|
|
7351
|
+
return null;
|
|
7352
|
+
}
|
|
7353
|
+
}
|
|
7354
|
+
async function runMnemosparkSlashHandler(ctx, options) {
|
|
7355
|
+
const route = routeMnemosparkArgs(ctx.args);
|
|
7356
|
+
if (route.kind === "root-help") {
|
|
7357
|
+
return { text: MNEMOSPARK_ROOT_HELP_TEXT };
|
|
7358
|
+
}
|
|
7359
|
+
if (route.kind === "error") {
|
|
7360
|
+
return { text: route.message, isError: true };
|
|
7361
|
+
}
|
|
7362
|
+
if (route.kind === "cloud") {
|
|
7363
|
+
const cloudCommandHandler = options?.cloudCommandHandler ?? getDefaultCloudCommandHandler();
|
|
7364
|
+
return cloudCommandHandler({ ...ctx, args: route.rest });
|
|
7365
|
+
}
|
|
7366
|
+
return handleWalletSlash(route.rest);
|
|
7367
|
+
}
|
|
7368
|
+
async function handleWalletSlash(rest) {
|
|
7369
|
+
const trimmed = rest.trim();
|
|
7370
|
+
if (!trimmed) {
|
|
7371
|
+
return buildWalletStatusResponse();
|
|
7372
|
+
}
|
|
7373
|
+
const { first, rest: afterFirst } = firstTokenAndRest(trimmed);
|
|
7374
|
+
const parsed = parseVerboseToken(first);
|
|
7375
|
+
if (!parsed.ok) {
|
|
7376
|
+
return {
|
|
7377
|
+
text: `Invalid token "${first}". Use name:true only with value true.`,
|
|
7378
|
+
isError: true
|
|
7379
|
+
};
|
|
7380
|
+
}
|
|
7381
|
+
if (parsed.name === "help") {
|
|
7382
|
+
if (afterFirst.trim()) {
|
|
7383
|
+
return {
|
|
7384
|
+
text: "Unexpected extra arguments after `help`. Use `/mnemospark wallet help` alone.",
|
|
7385
|
+
isError: true
|
|
7386
|
+
};
|
|
7387
|
+
}
|
|
7388
|
+
return buildWalletHelpResponse();
|
|
7389
|
+
}
|
|
7390
|
+
if (parsed.name === "export") {
|
|
7391
|
+
if (afterFirst.trim()) {
|
|
7392
|
+
return {
|
|
7393
|
+
text: "Unexpected extra arguments after `export`. Use `/mnemospark wallet export` alone.",
|
|
7394
|
+
isError: true
|
|
7395
|
+
};
|
|
7396
|
+
}
|
|
7397
|
+
return buildWalletExportResponse();
|
|
7398
|
+
}
|
|
7399
|
+
if (parsed.name === "status") {
|
|
7400
|
+
return buildWalletStatusResponse();
|
|
7401
|
+
}
|
|
7402
|
+
return {
|
|
7403
|
+
text: `Unknown wallet command "${parsed.name}". Try \`/mnemospark wallet help\`.`,
|
|
7404
|
+
isError: true
|
|
7405
|
+
};
|
|
7406
|
+
}
|
|
7407
|
+
async function buildWalletStatusResponse() {
|
|
7408
|
+
const wallet = resolveWalletFileSync();
|
|
7409
|
+
if (!wallet) {
|
|
7410
|
+
return {
|
|
7411
|
+
text: NO_WALLET_FOUND_TEXT,
|
|
7412
|
+
isError: true
|
|
7413
|
+
};
|
|
7414
|
+
}
|
|
7415
|
+
const { address } = wallet;
|
|
7416
|
+
let balanceText = "Balance: (checking...)";
|
|
7417
|
+
try {
|
|
7418
|
+
const monitor = new BalanceMonitor(address);
|
|
7419
|
+
const balance = await monitor.checkBalance();
|
|
7420
|
+
balanceText = `Balance: ${balance.balanceUSD}`;
|
|
7421
|
+
} catch {
|
|
7422
|
+
balanceText = "Balance: (could not check)";
|
|
7423
|
+
}
|
|
7424
|
+
return {
|
|
7425
|
+
text: [
|
|
7426
|
+
"\u2601\uFE0F **mnemospark Wallet**",
|
|
7427
|
+
"",
|
|
7428
|
+
`**Address:** \`${address}\``,
|
|
7429
|
+
`**${balanceText}**`,
|
|
7430
|
+
`**Key File:** \`${WALLET_FILE}\``,
|
|
7431
|
+
"",
|
|
7432
|
+
"**Commands:**",
|
|
7433
|
+
"\u2022 `/mnemospark wallet` \u2014 Show this status",
|
|
7434
|
+
"\u2022 `/mnemospark wallet help` \u2014 Commands and funding link",
|
|
7435
|
+
"\u2022 `/mnemospark wallet export` \u2014 Export private key for backup",
|
|
7436
|
+
"",
|
|
7437
|
+
`**Fund with USDC on Base:** https://basescan.org/address/${address}`
|
|
7438
|
+
].join("\n")
|
|
7439
|
+
};
|
|
7440
|
+
}
|
|
7441
|
+
async function buildWalletHelpResponse() {
|
|
7442
|
+
const wallet = resolveWalletFileSync();
|
|
7443
|
+
if (!wallet) {
|
|
7444
|
+
return {
|
|
7445
|
+
text: NO_WALLET_FOUND_TEXT,
|
|
7446
|
+
isError: true
|
|
7447
|
+
};
|
|
7448
|
+
}
|
|
7449
|
+
const { address } = wallet;
|
|
7450
|
+
return { text: MNEMOSPARK_WALLET_HELP_TEXT(address) };
|
|
7451
|
+
}
|
|
7452
|
+
async function buildWalletExportResponse() {
|
|
7453
|
+
const wallet = resolveWalletFileSync();
|
|
7454
|
+
if (!wallet) {
|
|
7455
|
+
return {
|
|
7456
|
+
text: NO_WALLET_FOUND_TEXT,
|
|
7457
|
+
isError: true
|
|
7458
|
+
};
|
|
7459
|
+
}
|
|
7460
|
+
const { walletKey, address } = wallet;
|
|
7461
|
+
const addressDisplay = address.replace(/\s/g, "");
|
|
7462
|
+
const keyDisplay = walletKey.replace(/\s/g, "");
|
|
7463
|
+
return {
|
|
7464
|
+
text: [
|
|
7465
|
+
"\u2601\uFE0F **mnemospark Wallet Export**",
|
|
7466
|
+
"",
|
|
7467
|
+
"\u26A0\uFE0F **SECURITY WARNING**: Your private key controls your wallet funds.",
|
|
7468
|
+
"Never share this key. Anyone with this key can spend your USDC.",
|
|
7469
|
+
"",
|
|
7470
|
+
`**Address:** \`${addressDisplay}\``,
|
|
7471
|
+
"",
|
|
7472
|
+
"**Private Key:**",
|
|
7473
|
+
`\`${keyDisplay}\``,
|
|
7474
|
+
"",
|
|
7475
|
+
"**To restore on a new machine:**",
|
|
7476
|
+
"1. Set the environment variable before running OpenClaw:",
|
|
7477
|
+
` \`export MNEMOSPARK_WALLET_KEY=${keyDisplay}\``,
|
|
7478
|
+
"2. Or save to file:",
|
|
7479
|
+
` \`mkdir -p ~/.openclaw/mnemospark/wallet && echo "${keyDisplay}" > ~/.openclaw/mnemospark/wallet/wallet.key && chmod 600 ~/.openclaw/mnemospark/wallet/wallet.key\``
|
|
7480
|
+
].join("\n")
|
|
7481
|
+
};
|
|
7482
|
+
}
|
|
7483
|
+
|
|
6836
7484
|
// src/cli.ts
|
|
6837
7485
|
import { spawn as spawn2 } from "child_process";
|
|
6838
7486
|
import { dirname as dirname6, join as join9 } from "path";
|
|
6839
7487
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
6840
7488
|
import { mkdir as mkdir6, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
|
|
6841
|
-
import { existsSync } from "fs";
|
|
7489
|
+
import { existsSync as existsSync2 } from "fs";
|
|
6842
7490
|
import { homedir as homedir7 } from "os";
|
|
6843
7491
|
function isHexPrivateKey(value) {
|
|
6844
7492
|
return typeof value === "string" && /^0x[0-9a-fA-F]{64}$/.test(value.trim());
|
|
@@ -6900,6 +7548,7 @@ function parseArgs(args) {
|
|
|
6900
7548
|
command: void 0,
|
|
6901
7549
|
installMode: void 0,
|
|
6902
7550
|
cloudArgs: void 0,
|
|
7551
|
+
walletArgs: void 0,
|
|
6903
7552
|
proxySubcommand: void 0
|
|
6904
7553
|
};
|
|
6905
7554
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -6913,6 +7562,8 @@ function parseArgs(args) {
|
|
|
6913
7562
|
result.command = "check-update";
|
|
6914
7563
|
} else if (arg === "wallet") {
|
|
6915
7564
|
result.command = "wallet";
|
|
7565
|
+
result.walletArgs = args.slice(i + 1).join(" ");
|
|
7566
|
+
return result;
|
|
6916
7567
|
} else if (arg === "cloud") {
|
|
6917
7568
|
result.command = "cloud";
|
|
6918
7569
|
result.cloudArgs = args.slice(i + 1).join(" ");
|
|
@@ -6951,11 +7602,11 @@ async function ensureDir(path) {
|
|
|
6951
7602
|
}
|
|
6952
7603
|
async function deployExtensionFiles() {
|
|
6953
7604
|
const scriptsSource = join9(PACKAGE_ROOT, "scripts");
|
|
6954
|
-
if (!
|
|
7605
|
+
if (!existsSync2(scriptsSource)) return;
|
|
6955
7606
|
const mnemoScriptsDir = join9(homedir7(), ".openclaw", "mnemospark", "scripts");
|
|
6956
7607
|
await ensureDir(mnemoScriptsDir);
|
|
6957
7608
|
const uninstallSrc = join9(scriptsSource, "uninstall.sh");
|
|
6958
|
-
if (
|
|
7609
|
+
if (existsSync2(uninstallSrc)) {
|
|
6959
7610
|
const content = await readFile4(uninstallSrc);
|
|
6960
7611
|
await writeFile4(join9(mnemoScriptsDir, "uninstall.sh"), content, { mode: 493 });
|
|
6961
7612
|
}
|
|
@@ -7159,28 +7810,15 @@ async function runInstall(mode) {
|
|
|
7159
7810
|
);
|
|
7160
7811
|
await promptOrRunOpenClawPluginInstall();
|
|
7161
7812
|
}
|
|
7162
|
-
async function
|
|
7163
|
-
const { address, source } = await resolveOrGenerateWalletKey();
|
|
7164
|
-
console.log(`[mnemospark] Wallet address: ${address}`);
|
|
7165
|
-
console.log(`[mnemospark] Key file: ${WALLET_FILE}`);
|
|
7166
|
-
if (source === "generated") {
|
|
7167
|
-
console.log("[mnemospark] New wallet generated and saved.");
|
|
7168
|
-
} else if (source === "saved") {
|
|
7169
|
-
console.log("[mnemospark] Loaded saved wallet.");
|
|
7170
|
-
} else {
|
|
7171
|
-
console.log("[mnemospark] Using wallet from MNEMOSPARK_WALLET_KEY.");
|
|
7172
|
-
}
|
|
7173
|
-
}
|
|
7174
|
-
async function runCloud(cloudArgs) {
|
|
7175
|
-
const cloudCmd = createCloudCommand();
|
|
7813
|
+
async function runMnemosparkCli(argsLine) {
|
|
7176
7814
|
const ctx = {
|
|
7177
7815
|
channel: "cli",
|
|
7178
7816
|
isAuthorizedSender: true,
|
|
7179
|
-
args:
|
|
7180
|
-
commandBody:
|
|
7817
|
+
args: argsLine.trim(),
|
|
7818
|
+
commandBody: argsLine.trim(),
|
|
7181
7819
|
config: {}
|
|
7182
7820
|
};
|
|
7183
|
-
const result = await
|
|
7821
|
+
const result = await runMnemosparkSlashHandler(ctx);
|
|
7184
7822
|
if (result.text) {
|
|
7185
7823
|
console.log(result.text);
|
|
7186
7824
|
}
|
|
@@ -7189,7 +7827,12 @@ async function runCloud(cloudArgs) {
|
|
|
7189
7827
|
}
|
|
7190
7828
|
}
|
|
7191
7829
|
async function main() {
|
|
7192
|
-
const
|
|
7830
|
+
const argv = process.argv.slice(2);
|
|
7831
|
+
if (argv.length === 1 && argv[0] === "help") {
|
|
7832
|
+
await runMnemosparkCli("help");
|
|
7833
|
+
return;
|
|
7834
|
+
}
|
|
7835
|
+
const args = parseArgs(argv);
|
|
7193
7836
|
if (args.version) {
|
|
7194
7837
|
console.log(VERSION);
|
|
7195
7838
|
process.exit(0);
|
|
@@ -7212,11 +7855,13 @@ async function main() {
|
|
|
7212
7855
|
return;
|
|
7213
7856
|
}
|
|
7214
7857
|
if (args.command === "wallet") {
|
|
7215
|
-
|
|
7858
|
+
const line = `wallet ${args.walletArgs ?? ""}`.trim();
|
|
7859
|
+
await runMnemosparkCli(line);
|
|
7216
7860
|
return;
|
|
7217
7861
|
}
|
|
7218
7862
|
if (args.command === "cloud") {
|
|
7219
|
-
|
|
7863
|
+
const line = `cloud ${args.cloudArgs ?? ""}`.trim();
|
|
7864
|
+
await runMnemosparkCli(line);
|
|
7220
7865
|
return;
|
|
7221
7866
|
}
|
|
7222
7867
|
if (args.command === "proxy") {
|