mnemospark 1.2.2 → 1.3.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 +18 -12
- package/dist/cli.js +278 -107
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +21 -6
- package/dist/index.js +260 -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,226 @@ 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 upload.`
|
|
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
|
+
const skipRestart = options.skipGatewayRestart ?? process.env.MNEMOSPARK_SKIP_GATEWAY_RESTART === "1";
|
|
4428
|
+
if (!skipRestart && (agentChanged || execChanged)) {
|
|
4429
|
+
try {
|
|
4430
|
+
await runOpenClawCli(["gateway", "restart", "--json"], homeDir);
|
|
4431
|
+
} catch {
|
|
4432
|
+
}
|
|
4433
|
+
}
|
|
4434
|
+
}
|
|
4435
|
+
|
|
4222
4436
|
// src/cloud-command.ts
|
|
4223
4437
|
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 =
|
|
4438
|
+
var BACKUP_DIR_SUBPATH = join10(".openclaw", "mnemospark", "backup");
|
|
4439
|
+
var DEFAULT_BACKUP_DIR = join10(homedir7(), BACKUP_DIR_SUBPATH);
|
|
4440
|
+
var BLOCKRUN_WALLET_KEY_SUBPATH = join10(".openclaw", "blockrun", "wallet.key");
|
|
4441
|
+
var MNEMOSPARK_WALLET_KEY_SUBPATH = join10(".openclaw", "mnemospark", "wallet", "wallet.key");
|
|
4228
4442
|
var INLINE_UPLOAD_MAX_BYTES = 45e5;
|
|
4229
4443
|
var NODE_FS_MAX_READFILE_BYTES = 2147483648;
|
|
4230
4444
|
var PAYMENT_CRON_SCHEDULE = "0 0 1 * *";
|
|
@@ -4242,10 +4456,10 @@ var ORCHESTRATOR_MODES = /* @__PURE__ */ new Set(["inline", "subagent"]);
|
|
|
4242
4456
|
function expandTilde(path) {
|
|
4243
4457
|
const trimmed = path.trim();
|
|
4244
4458
|
if (trimmed === "~") {
|
|
4245
|
-
return
|
|
4459
|
+
return homedir7();
|
|
4246
4460
|
}
|
|
4247
4461
|
if (trimmed.startsWith("~/") || trimmed.startsWith("~\\")) {
|
|
4248
|
-
return
|
|
4462
|
+
return join10(homedir7(), trimmed.slice(2));
|
|
4249
4463
|
}
|
|
4250
4464
|
return path;
|
|
4251
4465
|
}
|
|
@@ -4813,7 +5027,7 @@ async function calculateInputSizeBytes(targetPath) {
|
|
|
4813
5027
|
let total = 0;
|
|
4814
5028
|
const entries = await readdir2(targetPath, { withFileTypes: true });
|
|
4815
5029
|
for (const entry of entries) {
|
|
4816
|
-
total += await calculateInputSizeBytes(
|
|
5030
|
+
total += await calculateInputSizeBytes(join10(targetPath, entry.name));
|
|
4817
5031
|
}
|
|
4818
5032
|
return total;
|
|
4819
5033
|
}
|
|
@@ -4825,11 +5039,11 @@ function getAvailableDiskBytes(tmpDir, options) {
|
|
|
4825
5039
|
return stats.bavail * stats.bsize;
|
|
4826
5040
|
}
|
|
4827
5041
|
async function runTarGzip(archivePath, sourcePath) {
|
|
4828
|
-
const sourceDir =
|
|
5042
|
+
const sourceDir = dirname6(sourcePath);
|
|
4829
5043
|
const sourceName = basename2(sourcePath);
|
|
4830
5044
|
await new Promise((resolvePromise, rejectPromise) => {
|
|
4831
5045
|
let stderr = "";
|
|
4832
|
-
const child =
|
|
5046
|
+
const child = spawn2("tar", ["-czf", archivePath, "-C", sourceDir, sourceName], {
|
|
4833
5047
|
stdio: ["ignore", "ignore", "pipe"]
|
|
4834
5048
|
});
|
|
4835
5049
|
child.stderr.on("data", (chunk) => {
|
|
@@ -4859,7 +5073,7 @@ async function resolveLocalUploadArchivePath(backupDir, objectId, friendlyName)
|
|
|
4859
5073
|
if (friendlyName?.trim()) {
|
|
4860
5074
|
try {
|
|
4861
5075
|
const sanitized = sanitizeFriendlyNameForLocalBasename(friendlyName);
|
|
4862
|
-
const candidate =
|
|
5076
|
+
const candidate = join10(backupDir, sanitized);
|
|
4863
5077
|
try {
|
|
4864
5078
|
const st = await stat2(candidate);
|
|
4865
5079
|
if (st.isFile()) {
|
|
@@ -4870,7 +5084,7 @@ async function resolveLocalUploadArchivePath(backupDir, objectId, friendlyName)
|
|
|
4870
5084
|
} catch {
|
|
4871
5085
|
}
|
|
4872
5086
|
}
|
|
4873
|
-
const legacyPath =
|
|
5087
|
+
const legacyPath = join10(backupDir, objectId);
|
|
4874
5088
|
try {
|
|
4875
5089
|
const legacyStats = await stat2(legacyPath);
|
|
4876
5090
|
if (!legacyStats.isFile()) {
|
|
@@ -4908,7 +5122,7 @@ async function buildBackupObject(targetPathArg, options = {}) {
|
|
|
4908
5122
|
tmpStats = await stat2(tmpDir);
|
|
4909
5123
|
} catch (error) {
|
|
4910
5124
|
if (error.code === "ENOENT") {
|
|
4911
|
-
await
|
|
5125
|
+
await mkdir6(tmpDir, { recursive: true });
|
|
4912
5126
|
tmpStats = await stat2(tmpDir);
|
|
4913
5127
|
} else {
|
|
4914
5128
|
throw error;
|
|
@@ -4925,7 +5139,7 @@ async function buildBackupObject(targetPathArg, options = {}) {
|
|
|
4925
5139
|
}
|
|
4926
5140
|
const objectId = createObjectId(options);
|
|
4927
5141
|
const archiveBaseSegment = options.archiveBasename?.trim() || objectId;
|
|
4928
|
-
const archivePath =
|
|
5142
|
+
const archivePath = join10(tmpDir, archiveBaseSegment);
|
|
4929
5143
|
if (options.archiveBasename?.trim()) {
|
|
4930
5144
|
try {
|
|
4931
5145
|
const existing = await stat2(archivePath);
|
|
@@ -4981,48 +5195,6 @@ function normalizeOpenClawCronJobForLookup(value) {
|
|
|
4981
5195
|
message: payloadMessage
|
|
4982
5196
|
};
|
|
4983
5197
|
}
|
|
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
5198
|
function createOpenClawCliCronAdapter(homeDir) {
|
|
5027
5199
|
return {
|
|
5028
5200
|
add: async (job) => {
|
|
@@ -5038,11 +5210,11 @@ function createOpenClawCliCronAdapter(homeDir) {
|
|
|
5038
5210
|
job.schedule.tz,
|
|
5039
5211
|
"--session",
|
|
5040
5212
|
job.sessionTarget,
|
|
5213
|
+
"--agent",
|
|
5214
|
+
job.agentId,
|
|
5041
5215
|
"--message",
|
|
5042
5216
|
job.payload.message,
|
|
5043
|
-
"--
|
|
5044
|
-
"--description",
|
|
5045
|
-
job.delivery.text,
|
|
5217
|
+
"--no-deliver",
|
|
5046
5218
|
"--json"
|
|
5047
5219
|
],
|
|
5048
5220
|
homeDir
|
|
@@ -5107,8 +5279,9 @@ function buildStoragePaymentCronCommand(job) {
|
|
|
5107
5279
|
return `/mnemospark cloud ${buildStoragePaymentRenewalArgs(job)}`;
|
|
5108
5280
|
}
|
|
5109
5281
|
function buildOpenClawRenewalAgentMessage(openClawHome, renewalArgs) {
|
|
5110
|
-
const cliPath =
|
|
5111
|
-
|
|
5282
|
+
const cliPath = join10(openClawHome, ".openclaw/extensions/mnemospark/dist/cli.js");
|
|
5283
|
+
const nodeBin = getRenewalNodeBinary();
|
|
5284
|
+
return `Command: ${nodeBin} ${cliPath} cloud ${renewalArgs}`;
|
|
5112
5285
|
}
|
|
5113
5286
|
function parseStoragePaymentCronCommand(command) {
|
|
5114
5287
|
const objectIdMatch = command.match(/--object-id\s+("([^"\\]|\\.)*"|'([^'\\]|\\.)*'|\S+)/);
|
|
@@ -5154,10 +5327,7 @@ async function appendStoragePaymentCronJob(cronJob, adapter, payloadMessage) {
|
|
|
5154
5327
|
message: payloadMessage
|
|
5155
5328
|
},
|
|
5156
5329
|
sessionTarget: "isolated",
|
|
5157
|
-
|
|
5158
|
-
mode: "announce",
|
|
5159
|
-
text: "Thank you for using mnemospark cloud storage. Your renewal has been processed."
|
|
5160
|
-
}
|
|
5330
|
+
agentId: getRenewalAgentId()
|
|
5161
5331
|
};
|
|
5162
5332
|
return adapter.add(openClawJob);
|
|
5163
5333
|
}
|
|
@@ -5165,6 +5335,7 @@ async function removeStoragePaymentCronJob(cronId, adapter) {
|
|
|
5165
5335
|
return adapter.remove(cronId);
|
|
5166
5336
|
}
|
|
5167
5337
|
async function createStoragePaymentCronJob(upload, storagePrice, openClawCronAdapter, openClawHomeDir, nowDateFn = () => /* @__PURE__ */ new Date()) {
|
|
5338
|
+
await ensureOpenClawRenewalPrerequisites({ homeDir: openClawHomeDir });
|
|
5168
5339
|
const renewalFields = {
|
|
5169
5340
|
walletAddress: upload.addr,
|
|
5170
5341
|
objectId: upload.object_id,
|
|
@@ -5172,7 +5343,7 @@ async function createStoragePaymentCronJob(upload, storagePrice, openClawCronAda
|
|
|
5172
5343
|
storagePrice
|
|
5173
5344
|
};
|
|
5174
5345
|
const renewalArgs = buildStoragePaymentRenewalArgs(renewalFields);
|
|
5175
|
-
const provisionalCronId =
|
|
5346
|
+
const provisionalCronId = randomUUID4();
|
|
5176
5347
|
const cronJob = {
|
|
5177
5348
|
cronId: provisionalCronId,
|
|
5178
5349
|
createdAt: nowDateFn().toISOString(),
|
|
@@ -5196,7 +5367,7 @@ async function createStoragePaymentCronJob(upload, storagePrice, openClawCronAda
|
|
|
5196
5367
|
}
|
|
5197
5368
|
async function readWalletKeyIfPresent(walletPath) {
|
|
5198
5369
|
try {
|
|
5199
|
-
const key = (await
|
|
5370
|
+
const key = (await readFile4(walletPath, "utf-8")).trim();
|
|
5200
5371
|
return isValidWalletPrivateKey(key) ? key : null;
|
|
5201
5372
|
} catch (error) {
|
|
5202
5373
|
if (error.code === "ENOENT") {
|
|
@@ -5210,9 +5381,9 @@ async function resolveWalletPrivateKey(homeDir) {
|
|
|
5210
5381
|
if (isValidWalletPrivateKey(envKey)) {
|
|
5211
5382
|
return envKey;
|
|
5212
5383
|
}
|
|
5213
|
-
const baseHome = homeDir ??
|
|
5214
|
-
const primaryWalletPath =
|
|
5215
|
-
const fallbackWalletPath =
|
|
5384
|
+
const baseHome = homeDir ?? homedir7();
|
|
5385
|
+
const primaryWalletPath = join10(baseHome, MNEMOSPARK_WALLET_KEY_SUBPATH);
|
|
5386
|
+
const fallbackWalletPath = join10(baseHome, BLOCKRUN_WALLET_KEY_SUBPATH);
|
|
5216
5387
|
const fromPrimary = await readWalletKeyIfPresent(primaryWalletPath);
|
|
5217
5388
|
if (fromPrimary) {
|
|
5218
5389
|
return fromPrimary;
|
|
@@ -5276,9 +5447,9 @@ async function encryptPlaintextFileToAesGcmPath(plaintextPath, dek, outPath, ran
|
|
|
5276
5447
|
}
|
|
5277
5448
|
async function loadOrCreateKek(walletAddress, homeDir) {
|
|
5278
5449
|
const keyPath = resolveWalletKekPath(walletAddress, homeDir);
|
|
5279
|
-
await
|
|
5450
|
+
await mkdir6(dirname6(keyPath), { recursive: true });
|
|
5280
5451
|
try {
|
|
5281
|
-
const existing = await
|
|
5452
|
+
const existing = await readFile4(keyPath);
|
|
5282
5453
|
return { kek: parseStoredAes256Key(existing), keyPath };
|
|
5283
5454
|
} catch (error) {
|
|
5284
5455
|
if (error.code !== "ENOENT") {
|
|
@@ -5286,7 +5457,7 @@ async function loadOrCreateKek(walletAddress, homeDir) {
|
|
|
5286
5457
|
}
|
|
5287
5458
|
}
|
|
5288
5459
|
const generated = randomBytesNode(32);
|
|
5289
|
-
await
|
|
5460
|
+
await writeFile4(keyPath, generated, { mode: 384 });
|
|
5290
5461
|
return { kek: generated, keyPath };
|
|
5291
5462
|
}
|
|
5292
5463
|
async function prepareUploadPayload(archivePath, walletAddress, homeDir) {
|
|
@@ -5298,7 +5469,7 @@ async function prepareUploadPayload(archivePath, walletAddress, homeDir) {
|
|
|
5298
5469
|
const dek = randomBytesNode(32);
|
|
5299
5470
|
const wrappedDek = encryptAesGcm(dek, kek);
|
|
5300
5471
|
if (archiveStat.size >= NODE_FS_MAX_READFILE_BYTES) {
|
|
5301
|
-
const encryptedTempPath =
|
|
5472
|
+
const encryptedTempPath = join10(tmpdir(), `mnemospark-upload-${randomUUID4()}.enc`);
|
|
5302
5473
|
try {
|
|
5303
5474
|
await encryptPlaintextFileToAesGcmPath(archivePath, dek, encryptedTempPath);
|
|
5304
5475
|
const encStat = await stat2(encryptedTempPath);
|
|
@@ -5324,7 +5495,7 @@ async function prepareUploadPayload(archivePath, walletAddress, homeDir) {
|
|
|
5324
5495
|
throw err;
|
|
5325
5496
|
}
|
|
5326
5497
|
}
|
|
5327
|
-
const plaintext = await
|
|
5498
|
+
const plaintext = await readFile4(archivePath);
|
|
5328
5499
|
const encryptedContent = encryptAesGcm(plaintext, dek);
|
|
5329
5500
|
const payloadHash = sha256Buffer(encryptedContent);
|
|
5330
5501
|
const payload = {
|
|
@@ -5569,7 +5740,7 @@ function createInProcessSubagentOrchestrator() {
|
|
|
5569
5740
|
};
|
|
5570
5741
|
return {
|
|
5571
5742
|
dispatch: async (input) => {
|
|
5572
|
-
const sessionId = `agent:mnemospark:subagent:${
|
|
5743
|
+
const sessionId = `agent:mnemospark:subagent:${randomUUID4()}`;
|
|
5573
5744
|
const state = {
|
|
5574
5745
|
terminal: false,
|
|
5575
5746
|
cancelRequested: false,
|
|
@@ -5671,7 +5842,7 @@ function createCloudCommand(options = {}) {
|
|
|
5671
5842
|
createPaymentFetchFn: options.createPaymentFetchFn ?? createPaymentFetch,
|
|
5672
5843
|
fetchImpl: options.fetchImpl ?? fetch,
|
|
5673
5844
|
nowDateFn: options.nowDateFn ?? (() => /* @__PURE__ */ new Date()),
|
|
5674
|
-
idempotencyKeyFn: options.idempotencyKeyFn ??
|
|
5845
|
+
idempotencyKeyFn: options.idempotencyKeyFn ?? randomUUID4,
|
|
5675
5846
|
requestStorageLsFn: options.requestStorageLsFn ?? requestStorageLsViaProxy,
|
|
5676
5847
|
requestStorageDownloadFn: options.requestStorageDownloadFn ?? requestStorageDownloadViaProxy,
|
|
5677
5848
|
requestStorageDeleteFn: options.requestStorageDeleteFn ?? requestStorageDeleteViaProxy,
|
|
@@ -5815,8 +5986,8 @@ async function emitOperationEventBestEffort(eventType, context, homeDir) {
|
|
|
5815
5986
|
}
|
|
5816
5987
|
}
|
|
5817
5988
|
function buildRequestCorrelation(forcedOperationId, forcedTraceId) {
|
|
5818
|
-
const operationId = forcedOperationId?.trim() ||
|
|
5819
|
-
const traceId = forcedTraceId?.trim() ||
|
|
5989
|
+
const operationId = forcedOperationId?.trim() || randomUUID4();
|
|
5990
|
+
const traceId = forcedTraceId?.trim() || randomUUID4();
|
|
5820
5991
|
return { operationId, traceId };
|
|
5821
5992
|
}
|
|
5822
5993
|
function parseTransIdFromPaymentSettleBody(bodyText) {
|
|
@@ -6104,7 +6275,7 @@ ${operation.result_text}` : meta;
|
|
|
6104
6275
|
};
|
|
6105
6276
|
}
|
|
6106
6277
|
if (!isTerminalOperationStatus(operation.status)) {
|
|
6107
|
-
const traceId = operation.trace_id ??
|
|
6278
|
+
const traceId = operation.trace_id ?? randomUUID4();
|
|
6108
6279
|
const cancelRequestedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
6109
6280
|
await datastore.upsertOperation({
|
|
6110
6281
|
operation_id: operation.operation_id,
|
|
@@ -6702,7 +6873,7 @@ operation-id: ${operationId}`,
|
|
|
6702
6873
|
await emitCloudEventBestEffort(
|
|
6703
6874
|
"backup.completed",
|
|
6704
6875
|
{
|
|
6705
|
-
operation_id: executionContext.forcedOperationId?.trim() ||
|
|
6876
|
+
operation_id: executionContext.forcedOperationId?.trim() || randomUUID4(),
|
|
6706
6877
|
object_id: result.objectId,
|
|
6707
6878
|
status: "succeeded",
|
|
6708
6879
|
details: {
|
|
@@ -6989,7 +7160,7 @@ operation-id: ${operationId}`,
|
|
|
6989
7160
|
finalizedUploadResponse,
|
|
6990
7161
|
cronStoragePrice,
|
|
6991
7162
|
openClawCronAdapter,
|
|
6992
|
-
mnemosparkHomeDir ??
|
|
7163
|
+
mnemosparkHomeDir ?? homedir7(),
|
|
6993
7164
|
nowDateFn
|
|
6994
7165
|
);
|
|
6995
7166
|
await datastore.upsertObject({
|
|
@@ -7599,12 +7770,12 @@ async function buildWalletExportResponse() {
|
|
|
7599
7770
|
}
|
|
7600
7771
|
|
|
7601
7772
|
// src/cli.ts
|
|
7602
|
-
import { spawn as
|
|
7603
|
-
import { dirname as
|
|
7773
|
+
import { spawn as spawn3 } from "child_process";
|
|
7774
|
+
import { dirname as dirname7, join as join11 } from "path";
|
|
7604
7775
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
7605
|
-
import { mkdir as
|
|
7776
|
+
import { mkdir as mkdir7, readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
|
|
7606
7777
|
import { existsSync as existsSync2 } from "fs";
|
|
7607
|
-
import { homedir as
|
|
7778
|
+
import { homedir as homedir8 } from "os";
|
|
7608
7779
|
function isHexPrivateKey(value) {
|
|
7609
7780
|
return typeof value === "string" && /^0x[0-9a-fA-F]{64}$/.test(value.trim());
|
|
7610
7781
|
}
|
|
@@ -7712,25 +7883,25 @@ function parseArgs(args) {
|
|
|
7712
7883
|
return result;
|
|
7713
7884
|
}
|
|
7714
7885
|
var __filename2 = fileURLToPath2(import.meta.url);
|
|
7715
|
-
var __dirname2 =
|
|
7716
|
-
var PACKAGE_ROOT =
|
|
7886
|
+
var __dirname2 = dirname7(__filename2);
|
|
7887
|
+
var PACKAGE_ROOT = dirname7(__dirname2);
|
|
7717
7888
|
async function ensureDir(path) {
|
|
7718
|
-
await
|
|
7889
|
+
await mkdir7(path, { recursive: true });
|
|
7719
7890
|
}
|
|
7720
7891
|
async function deployExtensionFiles() {
|
|
7721
|
-
const scriptsSource =
|
|
7892
|
+
const scriptsSource = join11(PACKAGE_ROOT, "scripts");
|
|
7722
7893
|
if (!existsSync2(scriptsSource)) return;
|
|
7723
|
-
const mnemoScriptsDir =
|
|
7894
|
+
const mnemoScriptsDir = join11(homedir8(), ".openclaw", "mnemospark", "scripts");
|
|
7724
7895
|
await ensureDir(mnemoScriptsDir);
|
|
7725
|
-
const uninstallSrc =
|
|
7896
|
+
const uninstallSrc = join11(scriptsSource, "uninstall.sh");
|
|
7726
7897
|
if (existsSync2(uninstallSrc)) {
|
|
7727
|
-
const content = await
|
|
7728
|
-
await
|
|
7898
|
+
const content = await readFile5(uninstallSrc);
|
|
7899
|
+
await writeFile5(join11(mnemoScriptsDir, "uninstall.sh"), content, { mode: 493 });
|
|
7729
7900
|
}
|
|
7730
7901
|
}
|
|
7731
7902
|
function isOpenClawAvailable() {
|
|
7732
7903
|
return new Promise((resolve3) => {
|
|
7733
|
-
const child =
|
|
7904
|
+
const child = spawn3("openclaw", ["--version"], {
|
|
7734
7905
|
stdio: "ignore",
|
|
7735
7906
|
shell: true
|
|
7736
7907
|
});
|
|
@@ -7739,13 +7910,13 @@ function isOpenClawAvailable() {
|
|
|
7739
7910
|
});
|
|
7740
7911
|
}
|
|
7741
7912
|
function getOpenClawConfigPath() {
|
|
7742
|
-
const stateDir = process.env.OPENCLAW_STATE_DIR ??
|
|
7743
|
-
return
|
|
7913
|
+
const stateDir = process.env.OPENCLAW_STATE_DIR ?? join11(homedir8(), ".openclaw");
|
|
7914
|
+
return join11(stateDir, "openclaw.json");
|
|
7744
7915
|
}
|
|
7745
7916
|
async function ensureMnemosparkInPluginsAllow() {
|
|
7746
7917
|
const configPath = getOpenClawConfigPath();
|
|
7747
7918
|
try {
|
|
7748
|
-
const raw = await
|
|
7919
|
+
const raw = await readFile5(configPath, "utf-8");
|
|
7749
7920
|
const config = JSON.parse(raw);
|
|
7750
7921
|
if (!config.plugins || typeof config.plugins !== "object") {
|
|
7751
7922
|
config.plugins = {};
|
|
@@ -7757,7 +7928,7 @@ async function ensureMnemosparkInPluginsAllow() {
|
|
|
7757
7928
|
const allow = plugins.allow;
|
|
7758
7929
|
if (!allow.includes("mnemospark")) {
|
|
7759
7930
|
allow.push("mnemospark");
|
|
7760
|
-
await
|
|
7931
|
+
await writeFile5(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
7761
7932
|
console.log("[mnemospark] Added mnemospark to plugins.allow in openclaw.json.");
|
|
7762
7933
|
}
|
|
7763
7934
|
} catch (err) {
|
|
@@ -7770,7 +7941,7 @@ async function promptOrRunOpenClawPluginInstall() {
|
|
|
7770
7941
|
const available = await isOpenClawAvailable();
|
|
7771
7942
|
if (available) {
|
|
7772
7943
|
console.log("\n[mnemospark] Registering plugin with OpenClaw...");
|
|
7773
|
-
const child =
|
|
7944
|
+
const child = spawn3("openclaw", ["plugins", "install", "mnemospark"], {
|
|
7774
7945
|
stdio: "inherit",
|
|
7775
7946
|
shell: true
|
|
7776
7947
|
});
|
|
@@ -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() {
|