mnemospark 1.2.2 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -20
- package/dist/cli.js +286 -107
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +20 -6
- package/dist/index.js +259 -86
- package/dist/index.js.map +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +2 -2
- package/skills/mnemospark/references/commands.md +1 -0
package/dist/cli.js
CHANGED
|
@@ -3004,17 +3004,17 @@ var CLOUD_ONBOARDING_BLOCK_LINES = [
|
|
|
3004
3004
|
];
|
|
3005
3005
|
|
|
3006
3006
|
// src/cloud-command.ts
|
|
3007
|
-
import { spawn } from "child_process";
|
|
3007
|
+
import { spawn as spawn2 } from "child_process";
|
|
3008
3008
|
import {
|
|
3009
3009
|
createCipheriv,
|
|
3010
3010
|
createHash as createHash2,
|
|
3011
3011
|
randomBytes as randomBytesNode,
|
|
3012
|
-
randomUUID as
|
|
3012
|
+
randomUUID as randomUUID4
|
|
3013
3013
|
} from "crypto";
|
|
3014
3014
|
import { createReadStream as createReadStream2, createWriteStream as createWriteStream2, statfsSync } from "fs";
|
|
3015
|
-
import { lstat, mkdir as
|
|
3016
|
-
import { homedir as
|
|
3017
|
-
import { basename as basename2, dirname as
|
|
3015
|
+
import { lstat, mkdir as mkdir6, readFile as readFile4, readdir as readdir2, rm, stat as stat2, writeFile as writeFile4 } from "fs/promises";
|
|
3016
|
+
import { homedir as homedir7, tmpdir } from "os";
|
|
3017
|
+
import { basename as basename2, dirname as dirname6, join as join10, resolve as resolve2 } from "path";
|
|
3018
3018
|
import { Readable } from "stream";
|
|
3019
3019
|
import { finished } from "stream/promises";
|
|
3020
3020
|
import { privateKeyToAccount as privateKeyToAccount5 } from "viem/accounts";
|
|
@@ -4219,12 +4219,219 @@ var opStatusSchema = {
|
|
|
4219
4219
|
]
|
|
4220
4220
|
};
|
|
4221
4221
|
|
|
4222
|
+
// src/openclaw-cli.ts
|
|
4223
|
+
import { spawn } from "child_process";
|
|
4224
|
+
import { join as join8 } from "path";
|
|
4225
|
+
async function runOpenClawCli(args, homeDir) {
|
|
4226
|
+
return await new Promise((resolvePromise, rejectPromise) => {
|
|
4227
|
+
let stdout = "";
|
|
4228
|
+
let stderr = "";
|
|
4229
|
+
const child = spawn("openclaw", args, {
|
|
4230
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
4231
|
+
env: {
|
|
4232
|
+
...process.env,
|
|
4233
|
+
HOME: homeDir ?? process.env.HOME
|
|
4234
|
+
}
|
|
4235
|
+
});
|
|
4236
|
+
child.stdout.on("data", (chunk) => {
|
|
4237
|
+
stdout += chunk.toString();
|
|
4238
|
+
});
|
|
4239
|
+
child.stderr.on("data", (chunk) => {
|
|
4240
|
+
stderr += chunk.toString();
|
|
4241
|
+
});
|
|
4242
|
+
child.on("error", rejectPromise);
|
|
4243
|
+
child.on("close", (code) => {
|
|
4244
|
+
if (code === 0) {
|
|
4245
|
+
resolvePromise({ stdout, stderr });
|
|
4246
|
+
return;
|
|
4247
|
+
}
|
|
4248
|
+
rejectPromise(
|
|
4249
|
+
new Error(
|
|
4250
|
+
stderr.trim() || stdout.trim() || `openclaw ${args.join(" ")} exited with code ${code ?? "unknown"}`
|
|
4251
|
+
)
|
|
4252
|
+
);
|
|
4253
|
+
});
|
|
4254
|
+
});
|
|
4255
|
+
}
|
|
4256
|
+
function parseOpenClawCliJson(stdout, commandLabel) {
|
|
4257
|
+
const trimmed = stdout.trim();
|
|
4258
|
+
if (!trimmed) {
|
|
4259
|
+
throw new Error(`openclaw ${commandLabel} returned empty JSON output`);
|
|
4260
|
+
}
|
|
4261
|
+
try {
|
|
4262
|
+
return JSON.parse(trimmed);
|
|
4263
|
+
} catch {
|
|
4264
|
+
throw new Error(`openclaw ${commandLabel} returned invalid JSON output`);
|
|
4265
|
+
}
|
|
4266
|
+
}
|
|
4267
|
+
async function resolveOpenClawConfigFilePath(homeDir) {
|
|
4268
|
+
const { stdout } = await runOpenClawCli(["config", "file"], homeDir);
|
|
4269
|
+
const trimmed = stdout.trim();
|
|
4270
|
+
if (trimmed.startsWith("~/")) {
|
|
4271
|
+
return join8(homeDir, trimmed.slice(2));
|
|
4272
|
+
}
|
|
4273
|
+
if (trimmed.startsWith("~\\")) {
|
|
4274
|
+
return join8(homeDir, trimmed.slice(2));
|
|
4275
|
+
}
|
|
4276
|
+
return trimmed;
|
|
4277
|
+
}
|
|
4278
|
+
|
|
4279
|
+
// src/openclaw-renewal-runbook.ts
|
|
4280
|
+
import { mkdir as mkdir5, readFile as readFile3, rename as rename2, writeFile as writeFile3 } from "fs/promises";
|
|
4281
|
+
import { homedir as homedir6 } from "os";
|
|
4282
|
+
import { dirname as dirname5, join as join9 } from "path";
|
|
4283
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
4284
|
+
var DEFAULT_RENEWAL_AGENT_ID = "mnemospark-renewal";
|
|
4285
|
+
var RENEWAL_NODE_ALLOWLIST_ID = "node-usr-bin-node";
|
|
4286
|
+
function getRenewalAgentId() {
|
|
4287
|
+
const fromEnv = process.env.MNEMOSPARK_CRON_AGENT_ID?.trim();
|
|
4288
|
+
return fromEnv && fromEnv.length > 0 ? fromEnv : DEFAULT_RENEWAL_AGENT_ID;
|
|
4289
|
+
}
|
|
4290
|
+
function getRenewalNodeBinary() {
|
|
4291
|
+
const fromEnv = process.env.MNEMOSPARK_CRON_NODE_BIN?.trim();
|
|
4292
|
+
return fromEnv && fromEnv.length > 0 ? fromEnv : "/usr/bin/node";
|
|
4293
|
+
}
|
|
4294
|
+
function runbookRenewalAgentEntry(agentId = getRenewalAgentId()) {
|
|
4295
|
+
return {
|
|
4296
|
+
id: agentId,
|
|
4297
|
+
tools: {
|
|
4298
|
+
deny: ["subagents"],
|
|
4299
|
+
exec: { ask: "off" }
|
|
4300
|
+
}
|
|
4301
|
+
};
|
|
4302
|
+
}
|
|
4303
|
+
function isRecord(value) {
|
|
4304
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
4305
|
+
}
|
|
4306
|
+
function renewalAgentEntrySatisfied(existing, desired) {
|
|
4307
|
+
if (!isRecord(existing)) {
|
|
4308
|
+
return false;
|
|
4309
|
+
}
|
|
4310
|
+
if (existing.id !== desired.id) {
|
|
4311
|
+
return false;
|
|
4312
|
+
}
|
|
4313
|
+
const tools = existing.tools;
|
|
4314
|
+
if (!isRecord(tools)) {
|
|
4315
|
+
return false;
|
|
4316
|
+
}
|
|
4317
|
+
const deny = tools.deny;
|
|
4318
|
+
if (!Array.isArray(deny) || !deny.includes("subagents")) {
|
|
4319
|
+
return false;
|
|
4320
|
+
}
|
|
4321
|
+
const exec = tools.exec;
|
|
4322
|
+
if (!isRecord(exec) || exec.ask !== "off") {
|
|
4323
|
+
return false;
|
|
4324
|
+
}
|
|
4325
|
+
return true;
|
|
4326
|
+
}
|
|
4327
|
+
function mergeRenewalAgentIntoAgentsList(list, desired) {
|
|
4328
|
+
const arr = Array.isArray(list) ? [...list] : [];
|
|
4329
|
+
const idx = arr.findIndex((e) => isRecord(e) && typeof e.id === "string" && e.id === desired.id);
|
|
4330
|
+
if (idx === -1) {
|
|
4331
|
+
return { list: [...arr, desired], changed: true };
|
|
4332
|
+
}
|
|
4333
|
+
if (renewalAgentEntrySatisfied(arr[idx], desired)) {
|
|
4334
|
+
return { list: arr, changed: false };
|
|
4335
|
+
}
|
|
4336
|
+
const next = [...arr];
|
|
4337
|
+
next[idx] = desired;
|
|
4338
|
+
return { list: next, changed: true };
|
|
4339
|
+
}
|
|
4340
|
+
function mergeExecApprovalsAllowlist(doc, agentId, nodeBinary) {
|
|
4341
|
+
const prevAgents = doc.agents && isRecord(doc.agents) ? doc.agents : {};
|
|
4342
|
+
const block = prevAgents[agentId];
|
|
4343
|
+
const allowlist = Array.isArray(block?.allowlist) ? [...block.allowlist] : [];
|
|
4344
|
+
const hasPattern = allowlist.some((e) => e?.pattern === nodeBinary);
|
|
4345
|
+
if (hasPattern) {
|
|
4346
|
+
return { doc, changed: false };
|
|
4347
|
+
}
|
|
4348
|
+
allowlist.push({
|
|
4349
|
+
id: RENEWAL_NODE_ALLOWLIST_ID,
|
|
4350
|
+
pattern: nodeBinary,
|
|
4351
|
+
source: "manual",
|
|
4352
|
+
lastUsedAt: Date.now()
|
|
4353
|
+
});
|
|
4354
|
+
const nextAgents = {
|
|
4355
|
+
...prevAgents,
|
|
4356
|
+
[agentId]: {
|
|
4357
|
+
...block && isRecord(block) ? block : {},
|
|
4358
|
+
allowlist
|
|
4359
|
+
}
|
|
4360
|
+
};
|
|
4361
|
+
return { doc: { ...doc, agents: nextAgents }, changed: true };
|
|
4362
|
+
}
|
|
4363
|
+
async function readJsonFile(path) {
|
|
4364
|
+
const raw = await readFile3(path, "utf-8");
|
|
4365
|
+
return JSON.parse(raw);
|
|
4366
|
+
}
|
|
4367
|
+
async function writeFileAtomic(path, contents) {
|
|
4368
|
+
await mkdir5(dirname5(path), { recursive: true });
|
|
4369
|
+
const tmp = join9(dirname5(path), `.tmp-${randomUUID3()}`);
|
|
4370
|
+
await writeFile3(tmp, contents, "utf-8");
|
|
4371
|
+
await rename2(tmp, path);
|
|
4372
|
+
}
|
|
4373
|
+
async function ensureOpenClawRenewalPrerequisites(options = {}) {
|
|
4374
|
+
if (options.disabled ?? process.env.MNEMOSPARK_DISABLE_OPENCLAW_PREREQ === "1") {
|
|
4375
|
+
return;
|
|
4376
|
+
}
|
|
4377
|
+
const homeDir = options.homeDir ?? homedir6();
|
|
4378
|
+
const agentId = getRenewalAgentId();
|
|
4379
|
+
const desired = runbookRenewalAgentEntry(agentId);
|
|
4380
|
+
const nodeBinary = getRenewalNodeBinary();
|
|
4381
|
+
const configPath = await resolveOpenClawConfigFilePath(homeDir);
|
|
4382
|
+
let configRaw = "{}";
|
|
4383
|
+
try {
|
|
4384
|
+
configRaw = await readFile3(configPath, "utf-8");
|
|
4385
|
+
} catch (err) {
|
|
4386
|
+
if (err.code !== "ENOENT") {
|
|
4387
|
+
throw err;
|
|
4388
|
+
}
|
|
4389
|
+
}
|
|
4390
|
+
let parsed;
|
|
4391
|
+
try {
|
|
4392
|
+
parsed = JSON.parse(configRaw);
|
|
4393
|
+
} catch {
|
|
4394
|
+
throw new Error(
|
|
4395
|
+
`openclaw.json at ${configPath} is not valid JSON; fix or remove it before applying renewal prerequisites.`
|
|
4396
|
+
);
|
|
4397
|
+
}
|
|
4398
|
+
const agents = isRecord(parsed.agents) ? parsed.agents : {};
|
|
4399
|
+
const { list: mergedList, changed: agentChanged } = mergeRenewalAgentIntoAgentsList(
|
|
4400
|
+
agents.list,
|
|
4401
|
+
desired
|
|
4402
|
+
);
|
|
4403
|
+
if (agentChanged) {
|
|
4404
|
+
const listJson = JSON.stringify(mergedList);
|
|
4405
|
+
await runOpenClawCli(["config", "set", "agents.list", listJson, "--strict-json"], homeDir);
|
|
4406
|
+
await runOpenClawCli(["config", "validate"], homeDir);
|
|
4407
|
+
}
|
|
4408
|
+
const execPath = join9(homeDir, ".openclaw", "exec-approvals.json");
|
|
4409
|
+
let execDoc = {};
|
|
4410
|
+
try {
|
|
4411
|
+
const raw = await readJsonFile(execPath);
|
|
4412
|
+
execDoc = isRecord(raw) ? raw : {};
|
|
4413
|
+
} catch (err) {
|
|
4414
|
+
if (err.code !== "ENOENT") {
|
|
4415
|
+
throw err;
|
|
4416
|
+
}
|
|
4417
|
+
}
|
|
4418
|
+
const { doc: mergedExec, changed: execChanged } = mergeExecApprovalsAllowlist(
|
|
4419
|
+
execDoc,
|
|
4420
|
+
agentId,
|
|
4421
|
+
nodeBinary
|
|
4422
|
+
);
|
|
4423
|
+
if (execChanged) {
|
|
4424
|
+
await writeFileAtomic(execPath, `${JSON.stringify(mergedExec, null, 2)}
|
|
4425
|
+
`);
|
|
4426
|
+
}
|
|
4427
|
+
}
|
|
4428
|
+
|
|
4222
4429
|
// src/cloud-command.ts
|
|
4223
4430
|
var SUPPORTED_BACKUP_PLATFORMS = /* @__PURE__ */ new Set(["darwin", "linux"]);
|
|
4224
|
-
var BACKUP_DIR_SUBPATH =
|
|
4225
|
-
var DEFAULT_BACKUP_DIR =
|
|
4226
|
-
var BLOCKRUN_WALLET_KEY_SUBPATH =
|
|
4227
|
-
var MNEMOSPARK_WALLET_KEY_SUBPATH =
|
|
4431
|
+
var BACKUP_DIR_SUBPATH = join10(".openclaw", "mnemospark", "backup");
|
|
4432
|
+
var DEFAULT_BACKUP_DIR = join10(homedir7(), BACKUP_DIR_SUBPATH);
|
|
4433
|
+
var BLOCKRUN_WALLET_KEY_SUBPATH = join10(".openclaw", "blockrun", "wallet.key");
|
|
4434
|
+
var MNEMOSPARK_WALLET_KEY_SUBPATH = join10(".openclaw", "mnemospark", "wallet", "wallet.key");
|
|
4228
4435
|
var INLINE_UPLOAD_MAX_BYTES = 45e5;
|
|
4229
4436
|
var NODE_FS_MAX_READFILE_BYTES = 2147483648;
|
|
4230
4437
|
var PAYMENT_CRON_SCHEDULE = "0 0 1 * *";
|
|
@@ -4242,10 +4449,10 @@ var ORCHESTRATOR_MODES = /* @__PURE__ */ new Set(["inline", "subagent"]);
|
|
|
4242
4449
|
function expandTilde(path) {
|
|
4243
4450
|
const trimmed = path.trim();
|
|
4244
4451
|
if (trimmed === "~") {
|
|
4245
|
-
return
|
|
4452
|
+
return homedir7();
|
|
4246
4453
|
}
|
|
4247
4454
|
if (trimmed.startsWith("~/") || trimmed.startsWith("~\\")) {
|
|
4248
|
-
return
|
|
4455
|
+
return join10(homedir7(), trimmed.slice(2));
|
|
4249
4456
|
}
|
|
4250
4457
|
return path;
|
|
4251
4458
|
}
|
|
@@ -4813,7 +5020,7 @@ async function calculateInputSizeBytes(targetPath) {
|
|
|
4813
5020
|
let total = 0;
|
|
4814
5021
|
const entries = await readdir2(targetPath, { withFileTypes: true });
|
|
4815
5022
|
for (const entry of entries) {
|
|
4816
|
-
total += await calculateInputSizeBytes(
|
|
5023
|
+
total += await calculateInputSizeBytes(join10(targetPath, entry.name));
|
|
4817
5024
|
}
|
|
4818
5025
|
return total;
|
|
4819
5026
|
}
|
|
@@ -4825,11 +5032,11 @@ function getAvailableDiskBytes(tmpDir, options) {
|
|
|
4825
5032
|
return stats.bavail * stats.bsize;
|
|
4826
5033
|
}
|
|
4827
5034
|
async function runTarGzip(archivePath, sourcePath) {
|
|
4828
|
-
const sourceDir =
|
|
5035
|
+
const sourceDir = dirname6(sourcePath);
|
|
4829
5036
|
const sourceName = basename2(sourcePath);
|
|
4830
5037
|
await new Promise((resolvePromise, rejectPromise) => {
|
|
4831
5038
|
let stderr = "";
|
|
4832
|
-
const child =
|
|
5039
|
+
const child = spawn2("tar", ["-czf", archivePath, "-C", sourceDir, sourceName], {
|
|
4833
5040
|
stdio: ["ignore", "ignore", "pipe"]
|
|
4834
5041
|
});
|
|
4835
5042
|
child.stderr.on("data", (chunk) => {
|
|
@@ -4859,7 +5066,7 @@ async function resolveLocalUploadArchivePath(backupDir, objectId, friendlyName)
|
|
|
4859
5066
|
if (friendlyName?.trim()) {
|
|
4860
5067
|
try {
|
|
4861
5068
|
const sanitized = sanitizeFriendlyNameForLocalBasename(friendlyName);
|
|
4862
|
-
const candidate =
|
|
5069
|
+
const candidate = join10(backupDir, sanitized);
|
|
4863
5070
|
try {
|
|
4864
5071
|
const st = await stat2(candidate);
|
|
4865
5072
|
if (st.isFile()) {
|
|
@@ -4870,7 +5077,7 @@ async function resolveLocalUploadArchivePath(backupDir, objectId, friendlyName)
|
|
|
4870
5077
|
} catch {
|
|
4871
5078
|
}
|
|
4872
5079
|
}
|
|
4873
|
-
const legacyPath =
|
|
5080
|
+
const legacyPath = join10(backupDir, objectId);
|
|
4874
5081
|
try {
|
|
4875
5082
|
const legacyStats = await stat2(legacyPath);
|
|
4876
5083
|
if (!legacyStats.isFile()) {
|
|
@@ -4908,7 +5115,7 @@ async function buildBackupObject(targetPathArg, options = {}) {
|
|
|
4908
5115
|
tmpStats = await stat2(tmpDir);
|
|
4909
5116
|
} catch (error) {
|
|
4910
5117
|
if (error.code === "ENOENT") {
|
|
4911
|
-
await
|
|
5118
|
+
await mkdir6(tmpDir, { recursive: true });
|
|
4912
5119
|
tmpStats = await stat2(tmpDir);
|
|
4913
5120
|
} else {
|
|
4914
5121
|
throw error;
|
|
@@ -4925,7 +5132,7 @@ async function buildBackupObject(targetPathArg, options = {}) {
|
|
|
4925
5132
|
}
|
|
4926
5133
|
const objectId = createObjectId(options);
|
|
4927
5134
|
const archiveBaseSegment = options.archiveBasename?.trim() || objectId;
|
|
4928
|
-
const archivePath =
|
|
5135
|
+
const archivePath = join10(tmpDir, archiveBaseSegment);
|
|
4929
5136
|
if (options.archiveBasename?.trim()) {
|
|
4930
5137
|
try {
|
|
4931
5138
|
const existing = await stat2(archivePath);
|
|
@@ -4981,48 +5188,6 @@ function normalizeOpenClawCronJobForLookup(value) {
|
|
|
4981
5188
|
message: payloadMessage
|
|
4982
5189
|
};
|
|
4983
5190
|
}
|
|
4984
|
-
async function runOpenClawCli(args, homeDir) {
|
|
4985
|
-
return await new Promise((resolvePromise, rejectPromise) => {
|
|
4986
|
-
let stdout = "";
|
|
4987
|
-
let stderr = "";
|
|
4988
|
-
const child = spawn("openclaw", args, {
|
|
4989
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
4990
|
-
env: {
|
|
4991
|
-
...process.env,
|
|
4992
|
-
HOME: homeDir ?? process.env.HOME
|
|
4993
|
-
}
|
|
4994
|
-
});
|
|
4995
|
-
child.stdout.on("data", (chunk) => {
|
|
4996
|
-
stdout += chunk.toString();
|
|
4997
|
-
});
|
|
4998
|
-
child.stderr.on("data", (chunk) => {
|
|
4999
|
-
stderr += chunk.toString();
|
|
5000
|
-
});
|
|
5001
|
-
child.on("error", rejectPromise);
|
|
5002
|
-
child.on("close", (code) => {
|
|
5003
|
-
if (code === 0) {
|
|
5004
|
-
resolvePromise({ stdout, stderr });
|
|
5005
|
-
return;
|
|
5006
|
-
}
|
|
5007
|
-
rejectPromise(
|
|
5008
|
-
new Error(
|
|
5009
|
-
stderr.trim() || stdout.trim() || `openclaw ${args.join(" ")} exited with code ${code ?? "unknown"}`
|
|
5010
|
-
)
|
|
5011
|
-
);
|
|
5012
|
-
});
|
|
5013
|
-
});
|
|
5014
|
-
}
|
|
5015
|
-
function parseOpenClawCliJson(stdout, commandLabel) {
|
|
5016
|
-
const trimmed = stdout.trim();
|
|
5017
|
-
if (!trimmed) {
|
|
5018
|
-
throw new Error(`openclaw ${commandLabel} returned empty JSON output`);
|
|
5019
|
-
}
|
|
5020
|
-
try {
|
|
5021
|
-
return JSON.parse(trimmed);
|
|
5022
|
-
} catch {
|
|
5023
|
-
throw new Error(`openclaw ${commandLabel} returned invalid JSON output`);
|
|
5024
|
-
}
|
|
5025
|
-
}
|
|
5026
5191
|
function createOpenClawCliCronAdapter(homeDir) {
|
|
5027
5192
|
return {
|
|
5028
5193
|
add: async (job) => {
|
|
@@ -5038,11 +5203,11 @@ function createOpenClawCliCronAdapter(homeDir) {
|
|
|
5038
5203
|
job.schedule.tz,
|
|
5039
5204
|
"--session",
|
|
5040
5205
|
job.sessionTarget,
|
|
5206
|
+
"--agent",
|
|
5207
|
+
job.agentId,
|
|
5041
5208
|
"--message",
|
|
5042
5209
|
job.payload.message,
|
|
5043
|
-
"--
|
|
5044
|
-
"--description",
|
|
5045
|
-
job.delivery.text,
|
|
5210
|
+
"--no-deliver",
|
|
5046
5211
|
"--json"
|
|
5047
5212
|
],
|
|
5048
5213
|
homeDir
|
|
@@ -5107,8 +5272,9 @@ function buildStoragePaymentCronCommand(job) {
|
|
|
5107
5272
|
return `/mnemospark cloud ${buildStoragePaymentRenewalArgs(job)}`;
|
|
5108
5273
|
}
|
|
5109
5274
|
function buildOpenClawRenewalAgentMessage(openClawHome, renewalArgs) {
|
|
5110
|
-
const cliPath =
|
|
5111
|
-
|
|
5275
|
+
const cliPath = join10(openClawHome, ".openclaw/extensions/mnemospark/dist/cli.js");
|
|
5276
|
+
const nodeBin = getRenewalNodeBinary();
|
|
5277
|
+
return `Command: ${nodeBin} ${cliPath} cloud ${renewalArgs}`;
|
|
5112
5278
|
}
|
|
5113
5279
|
function parseStoragePaymentCronCommand(command) {
|
|
5114
5280
|
const objectIdMatch = command.match(/--object-id\s+("([^"\\]|\\.)*"|'([^'\\]|\\.)*'|\S+)/);
|
|
@@ -5154,10 +5320,7 @@ async function appendStoragePaymentCronJob(cronJob, adapter, payloadMessage) {
|
|
|
5154
5320
|
message: payloadMessage
|
|
5155
5321
|
},
|
|
5156
5322
|
sessionTarget: "isolated",
|
|
5157
|
-
|
|
5158
|
-
mode: "announce",
|
|
5159
|
-
text: "Thank you for using mnemospark cloud storage. Your renewal has been processed."
|
|
5160
|
-
}
|
|
5323
|
+
agentId: getRenewalAgentId()
|
|
5161
5324
|
};
|
|
5162
5325
|
return adapter.add(openClawJob);
|
|
5163
5326
|
}
|
|
@@ -5172,7 +5335,7 @@ async function createStoragePaymentCronJob(upload, storagePrice, openClawCronAda
|
|
|
5172
5335
|
storagePrice
|
|
5173
5336
|
};
|
|
5174
5337
|
const renewalArgs = buildStoragePaymentRenewalArgs(renewalFields);
|
|
5175
|
-
const provisionalCronId =
|
|
5338
|
+
const provisionalCronId = randomUUID4();
|
|
5176
5339
|
const cronJob = {
|
|
5177
5340
|
cronId: provisionalCronId,
|
|
5178
5341
|
createdAt: nowDateFn().toISOString(),
|
|
@@ -5196,7 +5359,7 @@ async function createStoragePaymentCronJob(upload, storagePrice, openClawCronAda
|
|
|
5196
5359
|
}
|
|
5197
5360
|
async function readWalletKeyIfPresent(walletPath) {
|
|
5198
5361
|
try {
|
|
5199
|
-
const key = (await
|
|
5362
|
+
const key = (await readFile4(walletPath, "utf-8")).trim();
|
|
5200
5363
|
return isValidWalletPrivateKey(key) ? key : null;
|
|
5201
5364
|
} catch (error) {
|
|
5202
5365
|
if (error.code === "ENOENT") {
|
|
@@ -5210,9 +5373,9 @@ async function resolveWalletPrivateKey(homeDir) {
|
|
|
5210
5373
|
if (isValidWalletPrivateKey(envKey)) {
|
|
5211
5374
|
return envKey;
|
|
5212
5375
|
}
|
|
5213
|
-
const baseHome = homeDir ??
|
|
5214
|
-
const primaryWalletPath =
|
|
5215
|
-
const fallbackWalletPath =
|
|
5376
|
+
const baseHome = homeDir ?? homedir7();
|
|
5377
|
+
const primaryWalletPath = join10(baseHome, MNEMOSPARK_WALLET_KEY_SUBPATH);
|
|
5378
|
+
const fallbackWalletPath = join10(baseHome, BLOCKRUN_WALLET_KEY_SUBPATH);
|
|
5216
5379
|
const fromPrimary = await readWalletKeyIfPresent(primaryWalletPath);
|
|
5217
5380
|
if (fromPrimary) {
|
|
5218
5381
|
return fromPrimary;
|
|
@@ -5276,9 +5439,9 @@ async function encryptPlaintextFileToAesGcmPath(plaintextPath, dek, outPath, ran
|
|
|
5276
5439
|
}
|
|
5277
5440
|
async function loadOrCreateKek(walletAddress, homeDir) {
|
|
5278
5441
|
const keyPath = resolveWalletKekPath(walletAddress, homeDir);
|
|
5279
|
-
await
|
|
5442
|
+
await mkdir6(dirname6(keyPath), { recursive: true });
|
|
5280
5443
|
try {
|
|
5281
|
-
const existing = await
|
|
5444
|
+
const existing = await readFile4(keyPath);
|
|
5282
5445
|
return { kek: parseStoredAes256Key(existing), keyPath };
|
|
5283
5446
|
} catch (error) {
|
|
5284
5447
|
if (error.code !== "ENOENT") {
|
|
@@ -5286,7 +5449,7 @@ async function loadOrCreateKek(walletAddress, homeDir) {
|
|
|
5286
5449
|
}
|
|
5287
5450
|
}
|
|
5288
5451
|
const generated = randomBytesNode(32);
|
|
5289
|
-
await
|
|
5452
|
+
await writeFile4(keyPath, generated, { mode: 384 });
|
|
5290
5453
|
return { kek: generated, keyPath };
|
|
5291
5454
|
}
|
|
5292
5455
|
async function prepareUploadPayload(archivePath, walletAddress, homeDir) {
|
|
@@ -5298,7 +5461,7 @@ async function prepareUploadPayload(archivePath, walletAddress, homeDir) {
|
|
|
5298
5461
|
const dek = randomBytesNode(32);
|
|
5299
5462
|
const wrappedDek = encryptAesGcm(dek, kek);
|
|
5300
5463
|
if (archiveStat.size >= NODE_FS_MAX_READFILE_BYTES) {
|
|
5301
|
-
const encryptedTempPath =
|
|
5464
|
+
const encryptedTempPath = join10(tmpdir(), `mnemospark-upload-${randomUUID4()}.enc`);
|
|
5302
5465
|
try {
|
|
5303
5466
|
await encryptPlaintextFileToAesGcmPath(archivePath, dek, encryptedTempPath);
|
|
5304
5467
|
const encStat = await stat2(encryptedTempPath);
|
|
@@ -5324,7 +5487,7 @@ async function prepareUploadPayload(archivePath, walletAddress, homeDir) {
|
|
|
5324
5487
|
throw err;
|
|
5325
5488
|
}
|
|
5326
5489
|
}
|
|
5327
|
-
const plaintext = await
|
|
5490
|
+
const plaintext = await readFile4(archivePath);
|
|
5328
5491
|
const encryptedContent = encryptAesGcm(plaintext, dek);
|
|
5329
5492
|
const payloadHash = sha256Buffer(encryptedContent);
|
|
5330
5493
|
const payload = {
|
|
@@ -5569,7 +5732,7 @@ function createInProcessSubagentOrchestrator() {
|
|
|
5569
5732
|
};
|
|
5570
5733
|
return {
|
|
5571
5734
|
dispatch: async (input) => {
|
|
5572
|
-
const sessionId = `agent:mnemospark:subagent:${
|
|
5735
|
+
const sessionId = `agent:mnemospark:subagent:${randomUUID4()}`;
|
|
5573
5736
|
const state = {
|
|
5574
5737
|
terminal: false,
|
|
5575
5738
|
cancelRequested: false,
|
|
@@ -5671,7 +5834,7 @@ function createCloudCommand(options = {}) {
|
|
|
5671
5834
|
createPaymentFetchFn: options.createPaymentFetchFn ?? createPaymentFetch,
|
|
5672
5835
|
fetchImpl: options.fetchImpl ?? fetch,
|
|
5673
5836
|
nowDateFn: options.nowDateFn ?? (() => /* @__PURE__ */ new Date()),
|
|
5674
|
-
idempotencyKeyFn: options.idempotencyKeyFn ??
|
|
5837
|
+
idempotencyKeyFn: options.idempotencyKeyFn ?? randomUUID4,
|
|
5675
5838
|
requestStorageLsFn: options.requestStorageLsFn ?? requestStorageLsViaProxy,
|
|
5676
5839
|
requestStorageDownloadFn: options.requestStorageDownloadFn ?? requestStorageDownloadViaProxy,
|
|
5677
5840
|
requestStorageDeleteFn: options.requestStorageDeleteFn ?? requestStorageDeleteViaProxy,
|
|
@@ -5815,8 +5978,8 @@ async function emitOperationEventBestEffort(eventType, context, homeDir) {
|
|
|
5815
5978
|
}
|
|
5816
5979
|
}
|
|
5817
5980
|
function buildRequestCorrelation(forcedOperationId, forcedTraceId) {
|
|
5818
|
-
const operationId = forcedOperationId?.trim() ||
|
|
5819
|
-
const traceId = forcedTraceId?.trim() ||
|
|
5981
|
+
const operationId = forcedOperationId?.trim() || randomUUID4();
|
|
5982
|
+
const traceId = forcedTraceId?.trim() || randomUUID4();
|
|
5820
5983
|
return { operationId, traceId };
|
|
5821
5984
|
}
|
|
5822
5985
|
function parseTransIdFromPaymentSettleBody(bodyText) {
|
|
@@ -6104,7 +6267,7 @@ ${operation.result_text}` : meta;
|
|
|
6104
6267
|
};
|
|
6105
6268
|
}
|
|
6106
6269
|
if (!isTerminalOperationStatus(operation.status)) {
|
|
6107
|
-
const traceId = operation.trace_id ??
|
|
6270
|
+
const traceId = operation.trace_id ?? randomUUID4();
|
|
6108
6271
|
const cancelRequestedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
6109
6272
|
await datastore.upsertOperation({
|
|
6110
6273
|
operation_id: operation.operation_id,
|
|
@@ -6702,7 +6865,7 @@ operation-id: ${operationId}`,
|
|
|
6702
6865
|
await emitCloudEventBestEffort(
|
|
6703
6866
|
"backup.completed",
|
|
6704
6867
|
{
|
|
6705
|
-
operation_id: executionContext.forcedOperationId?.trim() ||
|
|
6868
|
+
operation_id: executionContext.forcedOperationId?.trim() || randomUUID4(),
|
|
6706
6869
|
object_id: result.objectId,
|
|
6707
6870
|
status: "succeeded",
|
|
6708
6871
|
details: {
|
|
@@ -6989,7 +7152,7 @@ operation-id: ${operationId}`,
|
|
|
6989
7152
|
finalizedUploadResponse,
|
|
6990
7153
|
cronStoragePrice,
|
|
6991
7154
|
openClawCronAdapter,
|
|
6992
|
-
mnemosparkHomeDir ??
|
|
7155
|
+
mnemosparkHomeDir ?? homedir7(),
|
|
6993
7156
|
nowDateFn
|
|
6994
7157
|
);
|
|
6995
7158
|
await datastore.upsertObject({
|
|
@@ -7599,12 +7762,12 @@ async function buildWalletExportResponse() {
|
|
|
7599
7762
|
}
|
|
7600
7763
|
|
|
7601
7764
|
// src/cli.ts
|
|
7602
|
-
import { spawn as
|
|
7603
|
-
import { dirname as
|
|
7765
|
+
import { spawn as spawn3 } from "child_process";
|
|
7766
|
+
import { dirname as dirname7, join as join11 } from "path";
|
|
7604
7767
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
7605
|
-
import { mkdir as
|
|
7768
|
+
import { mkdir as mkdir7, readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
|
|
7606
7769
|
import { existsSync as existsSync2 } from "fs";
|
|
7607
|
-
import { homedir as
|
|
7770
|
+
import { homedir as homedir8 } from "os";
|
|
7608
7771
|
function isHexPrivateKey(value) {
|
|
7609
7772
|
return typeof value === "string" && /^0x[0-9a-fA-F]{64}$/.test(value.trim());
|
|
7610
7773
|
}
|
|
@@ -7712,25 +7875,25 @@ function parseArgs(args) {
|
|
|
7712
7875
|
return result;
|
|
7713
7876
|
}
|
|
7714
7877
|
var __filename2 = fileURLToPath2(import.meta.url);
|
|
7715
|
-
var __dirname2 =
|
|
7716
|
-
var PACKAGE_ROOT =
|
|
7878
|
+
var __dirname2 = dirname7(__filename2);
|
|
7879
|
+
var PACKAGE_ROOT = dirname7(__dirname2);
|
|
7717
7880
|
async function ensureDir(path) {
|
|
7718
|
-
await
|
|
7881
|
+
await mkdir7(path, { recursive: true });
|
|
7719
7882
|
}
|
|
7720
7883
|
async function deployExtensionFiles() {
|
|
7721
|
-
const scriptsSource =
|
|
7884
|
+
const scriptsSource = join11(PACKAGE_ROOT, "scripts");
|
|
7722
7885
|
if (!existsSync2(scriptsSource)) return;
|
|
7723
|
-
const mnemoScriptsDir =
|
|
7886
|
+
const mnemoScriptsDir = join11(homedir8(), ".openclaw", "mnemospark", "scripts");
|
|
7724
7887
|
await ensureDir(mnemoScriptsDir);
|
|
7725
|
-
const uninstallSrc =
|
|
7888
|
+
const uninstallSrc = join11(scriptsSource, "uninstall.sh");
|
|
7726
7889
|
if (existsSync2(uninstallSrc)) {
|
|
7727
|
-
const content = await
|
|
7728
|
-
await
|
|
7890
|
+
const content = await readFile5(uninstallSrc);
|
|
7891
|
+
await writeFile5(join11(mnemoScriptsDir, "uninstall.sh"), content, { mode: 493 });
|
|
7729
7892
|
}
|
|
7730
7893
|
}
|
|
7731
7894
|
function isOpenClawAvailable() {
|
|
7732
7895
|
return new Promise((resolve3) => {
|
|
7733
|
-
const child =
|
|
7896
|
+
const child = spawn3("openclaw", ["--version"], {
|
|
7734
7897
|
stdio: "ignore",
|
|
7735
7898
|
shell: true
|
|
7736
7899
|
});
|
|
@@ -7739,13 +7902,13 @@ function isOpenClawAvailable() {
|
|
|
7739
7902
|
});
|
|
7740
7903
|
}
|
|
7741
7904
|
function getOpenClawConfigPath() {
|
|
7742
|
-
const stateDir = process.env.OPENCLAW_STATE_DIR ??
|
|
7743
|
-
return
|
|
7905
|
+
const stateDir = process.env.OPENCLAW_STATE_DIR ?? join11(homedir8(), ".openclaw");
|
|
7906
|
+
return join11(stateDir, "openclaw.json");
|
|
7744
7907
|
}
|
|
7745
7908
|
async function ensureMnemosparkInPluginsAllow() {
|
|
7746
7909
|
const configPath = getOpenClawConfigPath();
|
|
7747
7910
|
try {
|
|
7748
|
-
const raw = await
|
|
7911
|
+
const raw = await readFile5(configPath, "utf-8");
|
|
7749
7912
|
const config = JSON.parse(raw);
|
|
7750
7913
|
if (!config.plugins || typeof config.plugins !== "object") {
|
|
7751
7914
|
config.plugins = {};
|
|
@@ -7757,7 +7920,7 @@ async function ensureMnemosparkInPluginsAllow() {
|
|
|
7757
7920
|
const allow = plugins.allow;
|
|
7758
7921
|
if (!allow.includes("mnemospark")) {
|
|
7759
7922
|
allow.push("mnemospark");
|
|
7760
|
-
await
|
|
7923
|
+
await writeFile5(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
7761
7924
|
console.log("[mnemospark] Added mnemospark to plugins.allow in openclaw.json.");
|
|
7762
7925
|
}
|
|
7763
7926
|
} catch (err) {
|
|
@@ -7770,7 +7933,7 @@ async function promptOrRunOpenClawPluginInstall() {
|
|
|
7770
7933
|
const available = await isOpenClawAvailable();
|
|
7771
7934
|
if (available) {
|
|
7772
7935
|
console.log("\n[mnemospark] Registering plugin with OpenClaw...");
|
|
7773
|
-
const child =
|
|
7936
|
+
const child = spawn3("openclaw", ["plugins", "install", "mnemospark"], {
|
|
7774
7937
|
stdio: "inherit",
|
|
7775
7938
|
shell: true
|
|
7776
7939
|
});
|
|
@@ -7779,6 +7942,14 @@ async function promptOrRunOpenClawPluginInstall() {
|
|
|
7779
7942
|
});
|
|
7780
7943
|
if (exitCode === 0) {
|
|
7781
7944
|
await ensureMnemosparkInPluginsAllow();
|
|
7945
|
+
try {
|
|
7946
|
+
await ensureOpenClawRenewalPrerequisites();
|
|
7947
|
+
} catch (err) {
|
|
7948
|
+
console.warn(
|
|
7949
|
+
"[mnemospark] Renewal prerequisites:",
|
|
7950
|
+
err instanceof Error ? err.message : String(err)
|
|
7951
|
+
);
|
|
7952
|
+
}
|
|
7782
7953
|
} else {
|
|
7783
7954
|
console.log(
|
|
7784
7955
|
"\n[mnemospark] OpenClaw plugin install did not succeed. Run manually: openclaw plugins install mnemospark"
|
|
@@ -7792,7 +7963,7 @@ async function promptOrRunOpenClawPluginInstall() {
|
|
|
7792
7963
|
}
|
|
7793
7964
|
async function readLegacyWalletIfPresent() {
|
|
7794
7965
|
try {
|
|
7795
|
-
const key = (await
|
|
7966
|
+
const key = (await readFile5(LEGACY_WALLET_FILE, "utf-8")).trim();
|
|
7796
7967
|
return isHexPrivateKey(key) ? key : null;
|
|
7797
7968
|
} catch (error) {
|
|
7798
7969
|
if (error.code === "ENOENT") {
|
|
@@ -7802,9 +7973,9 @@ async function readLegacyWalletIfPresent() {
|
|
|
7802
7973
|
}
|
|
7803
7974
|
}
|
|
7804
7975
|
async function writeMnemosparkWallet(key) {
|
|
7805
|
-
const dir =
|
|
7976
|
+
const dir = dirname7(WALLET_FILE);
|
|
7806
7977
|
await ensureDir(dir);
|
|
7807
|
-
await
|
|
7978
|
+
await writeFile5(WALLET_FILE, `${key}
|
|
7808
7979
|
`, { mode: 384 });
|
|
7809
7980
|
}
|
|
7810
7981
|
async function promptReuseLegacyWallet() {
|
|
@@ -7878,6 +8049,14 @@ async function runUpdate() {
|
|
|
7878
8049
|
try {
|
|
7879
8050
|
execSync(`npm install mnemospark@${latest}`, { stdio: "inherit" });
|
|
7880
8051
|
console.log(`[mnemospark] Updated to ${latest}.`);
|
|
8052
|
+
try {
|
|
8053
|
+
await ensureOpenClawRenewalPrerequisites();
|
|
8054
|
+
} catch (err) {
|
|
8055
|
+
console.warn(
|
|
8056
|
+
"[mnemospark] Renewal prerequisites:",
|
|
8057
|
+
err instanceof Error ? err.message : String(err)
|
|
8058
|
+
);
|
|
8059
|
+
}
|
|
7881
8060
|
} catch {
|
|
7882
8061
|
console.log(
|
|
7883
8062
|
"[mnemospark] npm install failed. You can update manually: npm install mnemospark@latest"
|