mnemospark 1.2.1 → 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 +42 -24
- package/dist/cli.js +366 -126
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +21 -6
- package/dist/index.js +348 -105
- package/dist/index.js.map +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +2 -2
- package/skills/mnemospark/SKILL.md +4 -2
- package/skills/mnemospark/references/commands.md +2 -1
- package/scripts/README.md +0 -55
- package/scripts/install-aws-cli.sh +0 -28
- package/scripts/install-jq.sh +0 -13
- package/scripts/install-pnpm.sh +0 -20
- package/scripts/reinstall.sh +0 -102
- package/scripts/uninstall.sh +0 -67
- package/scripts/verify-dev-tools.sh +0 -56
package/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";
|
|
@@ -4139,7 +4139,8 @@ var priceStorageSchema = {
|
|
|
4139
4139
|
args: [
|
|
4140
4140
|
{ name: "wallet-address", aliases: ["wallet"], required: true },
|
|
4141
4141
|
{ name: "object-id", aliases: ["object"], required: true },
|
|
4142
|
-
|
|
4142
|
+
// Optional: omit when the object exists in local SQLite after backup; CLI resolves sha256 from state.db.
|
|
4143
|
+
{ name: "object-id-hash", aliases: ["hash"] },
|
|
4143
4144
|
{ name: "gb", required: true },
|
|
4144
4145
|
{ name: "provider", required: true },
|
|
4145
4146
|
{ name: "region", required: true }
|
|
@@ -4218,12 +4219,226 @@ var opStatusSchema = {
|
|
|
4218
4219
|
]
|
|
4219
4220
|
};
|
|
4220
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
|
+
|
|
4221
4436
|
// src/cloud-command.ts
|
|
4222
4437
|
var SUPPORTED_BACKUP_PLATFORMS = /* @__PURE__ */ new Set(["darwin", "linux"]);
|
|
4223
|
-
var BACKUP_DIR_SUBPATH =
|
|
4224
|
-
var DEFAULT_BACKUP_DIR =
|
|
4225
|
-
var BLOCKRUN_WALLET_KEY_SUBPATH =
|
|
4226
|
-
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");
|
|
4227
4442
|
var INLINE_UPLOAD_MAX_BYTES = 45e5;
|
|
4228
4443
|
var NODE_FS_MAX_READFILE_BYTES = 2147483648;
|
|
4229
4444
|
var PAYMENT_CRON_SCHEDULE = "0 0 1 * *";
|
|
@@ -4231,7 +4446,7 @@ var TAR_OVERHEAD_BYTES = 10 * 1024 * 1024;
|
|
|
4231
4446
|
var QUOTE_VALIDITY_USER_NOTE = "Quotes are valid for one hour. Please run price-storage again if you need a new quote.";
|
|
4232
4447
|
var MNEMOSPARK_SUPPORT_EMAIL = "pluggedin@mnemospark.ai";
|
|
4233
4448
|
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.";
|
|
4234
|
-
var REQUIRED_PRICE_STORAGE = "wallet-address:, object-id:, object-id-hash
|
|
4449
|
+
var REQUIRED_PRICE_STORAGE = "wallet-address:, object-id:, gb:, provider:, region: (object-id-hash: optional if the object exists in local SQLite after backup)";
|
|
4235
4450
|
var REQUIRED_UPLOAD = "quote-id:, wallet-address:, object-id:, object-id-hash:";
|
|
4236
4451
|
var REQUIRED_BACKUP = "<file|directory> and name:<friendly-name>";
|
|
4237
4452
|
var REQUIRED_PAYMENT_SETTLE = "wallet-address: and (quote-id: | renewal:true with object-key:)";
|
|
@@ -4241,10 +4456,10 @@ var ORCHESTRATOR_MODES = /* @__PURE__ */ new Set(["inline", "subagent"]);
|
|
|
4241
4456
|
function expandTilde(path) {
|
|
4242
4457
|
const trimmed = path.trim();
|
|
4243
4458
|
if (trimmed === "~") {
|
|
4244
|
-
return
|
|
4459
|
+
return homedir7();
|
|
4245
4460
|
}
|
|
4246
4461
|
if (trimmed.startsWith("~/") || trimmed.startsWith("~\\")) {
|
|
4247
|
-
return
|
|
4462
|
+
return join10(homedir7(), trimmed.slice(2));
|
|
4248
4463
|
}
|
|
4249
4464
|
return path;
|
|
4250
4465
|
}
|
|
@@ -4261,10 +4476,10 @@ var CLOUD_HELP_TEXT = [
|
|
|
4261
4476
|
" 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.",
|
|
4262
4477
|
" Required: " + REQUIRED_BACKUP,
|
|
4263
4478
|
"",
|
|
4264
|
-
"\u2022 `/mnemospark cloud price-storage wallet-address:<addr> object-id:<id> object-id-hash:<hash> gb:<gb> provider:aws region:us-east-1`",
|
|
4265
|
-
" Purpose: request a storage quote before upload (defaults shown; override `provider:` / `region:` for other regions).",
|
|
4479
|
+
"\u2022 `/mnemospark cloud price-storage wallet-address:<addr> object-id:<id> [object-id-hash:<hash>] gb:<gb> provider:aws region:us-east-1`",
|
|
4480
|
+
" Purpose: request a storage quote before upload (defaults shown; override `provider:` / `region:` for other regions). Omit `object-id-hash:` when the object is already in local SQLite (e.g. after backup); mnemospark reads sha256 from ~/.openclaw/mnemospark/state.db.",
|
|
4266
4481
|
" Required: " + REQUIRED_PRICE_STORAGE,
|
|
4267
|
-
" Shorter: `wallet:\u2026 object:\u2026 hash:\u2026 gb:\u2026 provider:\u2026 region:\u2026`",
|
|
4482
|
+
" Shorter: `wallet:\u2026 object:\u2026 [hash:\u2026] gb:\u2026 provider:\u2026 region:\u2026`",
|
|
4268
4483
|
"",
|
|
4269
4484
|
"\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>]`",
|
|
4270
4485
|
" Purpose: upload an encrypted object using a valid quote-id.",
|
|
@@ -4475,6 +4690,41 @@ function stripAsyncControlFlags(args) {
|
|
|
4475
4690
|
function mergeArgParseWarnings(a, b) {
|
|
4476
4691
|
return [...a, ...b];
|
|
4477
4692
|
}
|
|
4693
|
+
async function resolvePriceStorageHashFromDatastore(datastore, partial) {
|
|
4694
|
+
await datastore.ensureReady();
|
|
4695
|
+
const row = await datastore.findObjectById(partial.object_id.trim());
|
|
4696
|
+
const wallet = partial.wallet_address.trim().toLowerCase();
|
|
4697
|
+
if (!row) {
|
|
4698
|
+
return {
|
|
4699
|
+
ok: false,
|
|
4700
|
+
message: "Cannot resolve object-id-hash: no object found in local SQLite for this object-id. Run backup first, or pass --object-id-hash explicitly."
|
|
4701
|
+
};
|
|
4702
|
+
}
|
|
4703
|
+
if (row.wallet_address.trim().toLowerCase() !== wallet) {
|
|
4704
|
+
return {
|
|
4705
|
+
ok: false,
|
|
4706
|
+
message: "Cannot resolve object-id-hash: wallet-address does not match the object record in ~/.openclaw/mnemospark/state.db."
|
|
4707
|
+
};
|
|
4708
|
+
}
|
|
4709
|
+
const sha = row.sha256?.trim();
|
|
4710
|
+
if (!sha) {
|
|
4711
|
+
return {
|
|
4712
|
+
ok: false,
|
|
4713
|
+
message: "Cannot resolve object-id-hash: local object record has no sha256 yet. Run backup first, or pass --object-id-hash explicitly."
|
|
4714
|
+
};
|
|
4715
|
+
}
|
|
4716
|
+
return {
|
|
4717
|
+
ok: true,
|
|
4718
|
+
request: {
|
|
4719
|
+
wallet_address: partial.wallet_address.trim(),
|
|
4720
|
+
object_id: partial.object_id.trim(),
|
|
4721
|
+
object_id_hash: sha.replace(/\s/g, ""),
|
|
4722
|
+
gb: partial.gb,
|
|
4723
|
+
provider: partial.provider.trim(),
|
|
4724
|
+
region: partial.region.trim()
|
|
4725
|
+
}
|
|
4726
|
+
};
|
|
4727
|
+
}
|
|
4478
4728
|
function parseCloudArgs(args) {
|
|
4479
4729
|
const trimmed = args?.trim() ?? "";
|
|
4480
4730
|
if (!trimmed) {
|
|
@@ -4544,18 +4794,38 @@ function parseCloudArgs(args) {
|
|
|
4544
4794
|
}
|
|
4545
4795
|
const flags = valuesToStringRecord(parsed.values);
|
|
4546
4796
|
const gb = Number.parseFloat(flags.gb ?? "");
|
|
4547
|
-
const
|
|
4548
|
-
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
region: flags.region
|
|
4554
|
-
});
|
|
4555
|
-
if (!request) {
|
|
4797
|
+
const hashRaw = flags["object-id-hash"]?.trim();
|
|
4798
|
+
const walletAddress = flags["wallet-address"]?.trim();
|
|
4799
|
+
const objectId = flags["object-id"]?.trim();
|
|
4800
|
+
const provider = flags.provider?.trim();
|
|
4801
|
+
const region = flags.region?.trim();
|
|
4802
|
+
if (!walletAddress || !objectId || !provider || !region || !Number.isFinite(gb)) {
|
|
4556
4803
|
return { mode: "price-storage-invalid" };
|
|
4557
4804
|
}
|
|
4558
|
-
|
|
4805
|
+
if (hashRaw) {
|
|
4806
|
+
const request = parsePriceStorageQuoteRequest({
|
|
4807
|
+
wallet_address: walletAddress,
|
|
4808
|
+
object_id: objectId,
|
|
4809
|
+
object_id_hash: hashRaw,
|
|
4810
|
+
gb,
|
|
4811
|
+
provider,
|
|
4812
|
+
region
|
|
4813
|
+
});
|
|
4814
|
+
if (!request) {
|
|
4815
|
+
return { mode: "price-storage-invalid" };
|
|
4816
|
+
}
|
|
4817
|
+
return { mode: "price-storage", priceStorageRequest: request };
|
|
4818
|
+
}
|
|
4819
|
+
return {
|
|
4820
|
+
mode: "price-storage-resolve-hash",
|
|
4821
|
+
priceStoragePartial: {
|
|
4822
|
+
wallet_address: walletAddress,
|
|
4823
|
+
object_id: objectId,
|
|
4824
|
+
gb,
|
|
4825
|
+
provider,
|
|
4826
|
+
region
|
|
4827
|
+
}
|
|
4828
|
+
};
|
|
4559
4829
|
}
|
|
4560
4830
|
if (subcommand === "upload") {
|
|
4561
4831
|
const parsed = parseCommandArgs(rest, uploadSchema);
|
|
@@ -4757,7 +5027,7 @@ async function calculateInputSizeBytes(targetPath) {
|
|
|
4757
5027
|
let total = 0;
|
|
4758
5028
|
const entries = await readdir2(targetPath, { withFileTypes: true });
|
|
4759
5029
|
for (const entry of entries) {
|
|
4760
|
-
total += await calculateInputSizeBytes(
|
|
5030
|
+
total += await calculateInputSizeBytes(join10(targetPath, entry.name));
|
|
4761
5031
|
}
|
|
4762
5032
|
return total;
|
|
4763
5033
|
}
|
|
@@ -4769,11 +5039,11 @@ function getAvailableDiskBytes(tmpDir, options) {
|
|
|
4769
5039
|
return stats.bavail * stats.bsize;
|
|
4770
5040
|
}
|
|
4771
5041
|
async function runTarGzip(archivePath, sourcePath) {
|
|
4772
|
-
const sourceDir =
|
|
5042
|
+
const sourceDir = dirname6(sourcePath);
|
|
4773
5043
|
const sourceName = basename2(sourcePath);
|
|
4774
5044
|
await new Promise((resolvePromise, rejectPromise) => {
|
|
4775
5045
|
let stderr = "";
|
|
4776
|
-
const child =
|
|
5046
|
+
const child = spawn2("tar", ["-czf", archivePath, "-C", sourceDir, sourceName], {
|
|
4777
5047
|
stdio: ["ignore", "ignore", "pipe"]
|
|
4778
5048
|
});
|
|
4779
5049
|
child.stderr.on("data", (chunk) => {
|
|
@@ -4803,7 +5073,7 @@ async function resolveLocalUploadArchivePath(backupDir, objectId, friendlyName)
|
|
|
4803
5073
|
if (friendlyName?.trim()) {
|
|
4804
5074
|
try {
|
|
4805
5075
|
const sanitized = sanitizeFriendlyNameForLocalBasename(friendlyName);
|
|
4806
|
-
const candidate =
|
|
5076
|
+
const candidate = join10(backupDir, sanitized);
|
|
4807
5077
|
try {
|
|
4808
5078
|
const st = await stat2(candidate);
|
|
4809
5079
|
if (st.isFile()) {
|
|
@@ -4814,7 +5084,7 @@ async function resolveLocalUploadArchivePath(backupDir, objectId, friendlyName)
|
|
|
4814
5084
|
} catch {
|
|
4815
5085
|
}
|
|
4816
5086
|
}
|
|
4817
|
-
const legacyPath =
|
|
5087
|
+
const legacyPath = join10(backupDir, objectId);
|
|
4818
5088
|
try {
|
|
4819
5089
|
const legacyStats = await stat2(legacyPath);
|
|
4820
5090
|
if (!legacyStats.isFile()) {
|
|
@@ -4852,7 +5122,7 @@ async function buildBackupObject(targetPathArg, options = {}) {
|
|
|
4852
5122
|
tmpStats = await stat2(tmpDir);
|
|
4853
5123
|
} catch (error) {
|
|
4854
5124
|
if (error.code === "ENOENT") {
|
|
4855
|
-
await
|
|
5125
|
+
await mkdir6(tmpDir, { recursive: true });
|
|
4856
5126
|
tmpStats = await stat2(tmpDir);
|
|
4857
5127
|
} else {
|
|
4858
5128
|
throw error;
|
|
@@ -4869,7 +5139,7 @@ async function buildBackupObject(targetPathArg, options = {}) {
|
|
|
4869
5139
|
}
|
|
4870
5140
|
const objectId = createObjectId(options);
|
|
4871
5141
|
const archiveBaseSegment = options.archiveBasename?.trim() || objectId;
|
|
4872
|
-
const archivePath =
|
|
5142
|
+
const archivePath = join10(tmpDir, archiveBaseSegment);
|
|
4873
5143
|
if (options.archiveBasename?.trim()) {
|
|
4874
5144
|
try {
|
|
4875
5145
|
const existing = await stat2(archivePath);
|
|
@@ -4925,48 +5195,6 @@ function normalizeOpenClawCronJobForLookup(value) {
|
|
|
4925
5195
|
message: payloadMessage
|
|
4926
5196
|
};
|
|
4927
5197
|
}
|
|
4928
|
-
async function runOpenClawCli(args, homeDir) {
|
|
4929
|
-
return await new Promise((resolvePromise, rejectPromise) => {
|
|
4930
|
-
let stdout = "";
|
|
4931
|
-
let stderr = "";
|
|
4932
|
-
const child = spawn("openclaw", args, {
|
|
4933
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
4934
|
-
env: {
|
|
4935
|
-
...process.env,
|
|
4936
|
-
HOME: homeDir ?? process.env.HOME
|
|
4937
|
-
}
|
|
4938
|
-
});
|
|
4939
|
-
child.stdout.on("data", (chunk) => {
|
|
4940
|
-
stdout += chunk.toString();
|
|
4941
|
-
});
|
|
4942
|
-
child.stderr.on("data", (chunk) => {
|
|
4943
|
-
stderr += chunk.toString();
|
|
4944
|
-
});
|
|
4945
|
-
child.on("error", rejectPromise);
|
|
4946
|
-
child.on("close", (code) => {
|
|
4947
|
-
if (code === 0) {
|
|
4948
|
-
resolvePromise({ stdout, stderr });
|
|
4949
|
-
return;
|
|
4950
|
-
}
|
|
4951
|
-
rejectPromise(
|
|
4952
|
-
new Error(
|
|
4953
|
-
stderr.trim() || stdout.trim() || `openclaw ${args.join(" ")} exited with code ${code ?? "unknown"}`
|
|
4954
|
-
)
|
|
4955
|
-
);
|
|
4956
|
-
});
|
|
4957
|
-
});
|
|
4958
|
-
}
|
|
4959
|
-
function parseOpenClawCliJson(stdout, commandLabel) {
|
|
4960
|
-
const trimmed = stdout.trim();
|
|
4961
|
-
if (!trimmed) {
|
|
4962
|
-
throw new Error(`openclaw ${commandLabel} returned empty JSON output`);
|
|
4963
|
-
}
|
|
4964
|
-
try {
|
|
4965
|
-
return JSON.parse(trimmed);
|
|
4966
|
-
} catch {
|
|
4967
|
-
throw new Error(`openclaw ${commandLabel} returned invalid JSON output`);
|
|
4968
|
-
}
|
|
4969
|
-
}
|
|
4970
5198
|
function createOpenClawCliCronAdapter(homeDir) {
|
|
4971
5199
|
return {
|
|
4972
5200
|
add: async (job) => {
|
|
@@ -4982,11 +5210,11 @@ function createOpenClawCliCronAdapter(homeDir) {
|
|
|
4982
5210
|
job.schedule.tz,
|
|
4983
5211
|
"--session",
|
|
4984
5212
|
job.sessionTarget,
|
|
5213
|
+
"--agent",
|
|
5214
|
+
job.agentId,
|
|
4985
5215
|
"--message",
|
|
4986
5216
|
job.payload.message,
|
|
4987
|
-
"--
|
|
4988
|
-
"--description",
|
|
4989
|
-
job.delivery.text,
|
|
5217
|
+
"--no-deliver",
|
|
4990
5218
|
"--json"
|
|
4991
5219
|
],
|
|
4992
5220
|
homeDir
|
|
@@ -5051,8 +5279,9 @@ function buildStoragePaymentCronCommand(job) {
|
|
|
5051
5279
|
return `/mnemospark cloud ${buildStoragePaymentRenewalArgs(job)}`;
|
|
5052
5280
|
}
|
|
5053
5281
|
function buildOpenClawRenewalAgentMessage(openClawHome, renewalArgs) {
|
|
5054
|
-
const cliPath =
|
|
5055
|
-
|
|
5282
|
+
const cliPath = join10(openClawHome, ".openclaw/extensions/mnemospark/dist/cli.js");
|
|
5283
|
+
const nodeBin = getRenewalNodeBinary();
|
|
5284
|
+
return `Command: ${nodeBin} ${cliPath} cloud ${renewalArgs}`;
|
|
5056
5285
|
}
|
|
5057
5286
|
function parseStoragePaymentCronCommand(command) {
|
|
5058
5287
|
const objectIdMatch = command.match(/--object-id\s+("([^"\\]|\\.)*"|'([^'\\]|\\.)*'|\S+)/);
|
|
@@ -5098,10 +5327,7 @@ async function appendStoragePaymentCronJob(cronJob, adapter, payloadMessage) {
|
|
|
5098
5327
|
message: payloadMessage
|
|
5099
5328
|
},
|
|
5100
5329
|
sessionTarget: "isolated",
|
|
5101
|
-
|
|
5102
|
-
mode: "announce",
|
|
5103
|
-
text: "Thank you for using mnemospark cloud storage. Your renewal has been processed."
|
|
5104
|
-
}
|
|
5330
|
+
agentId: getRenewalAgentId()
|
|
5105
5331
|
};
|
|
5106
5332
|
return adapter.add(openClawJob);
|
|
5107
5333
|
}
|
|
@@ -5109,6 +5335,7 @@ async function removeStoragePaymentCronJob(cronId, adapter) {
|
|
|
5109
5335
|
return adapter.remove(cronId);
|
|
5110
5336
|
}
|
|
5111
5337
|
async function createStoragePaymentCronJob(upload, storagePrice, openClawCronAdapter, openClawHomeDir, nowDateFn = () => /* @__PURE__ */ new Date()) {
|
|
5338
|
+
await ensureOpenClawRenewalPrerequisites({ homeDir: openClawHomeDir });
|
|
5112
5339
|
const renewalFields = {
|
|
5113
5340
|
walletAddress: upload.addr,
|
|
5114
5341
|
objectId: upload.object_id,
|
|
@@ -5116,7 +5343,7 @@ async function createStoragePaymentCronJob(upload, storagePrice, openClawCronAda
|
|
|
5116
5343
|
storagePrice
|
|
5117
5344
|
};
|
|
5118
5345
|
const renewalArgs = buildStoragePaymentRenewalArgs(renewalFields);
|
|
5119
|
-
const provisionalCronId =
|
|
5346
|
+
const provisionalCronId = randomUUID4();
|
|
5120
5347
|
const cronJob = {
|
|
5121
5348
|
cronId: provisionalCronId,
|
|
5122
5349
|
createdAt: nowDateFn().toISOString(),
|
|
@@ -5140,7 +5367,7 @@ async function createStoragePaymentCronJob(upload, storagePrice, openClawCronAda
|
|
|
5140
5367
|
}
|
|
5141
5368
|
async function readWalletKeyIfPresent(walletPath) {
|
|
5142
5369
|
try {
|
|
5143
|
-
const key = (await
|
|
5370
|
+
const key = (await readFile4(walletPath, "utf-8")).trim();
|
|
5144
5371
|
return isValidWalletPrivateKey(key) ? key : null;
|
|
5145
5372
|
} catch (error) {
|
|
5146
5373
|
if (error.code === "ENOENT") {
|
|
@@ -5154,9 +5381,9 @@ async function resolveWalletPrivateKey(homeDir) {
|
|
|
5154
5381
|
if (isValidWalletPrivateKey(envKey)) {
|
|
5155
5382
|
return envKey;
|
|
5156
5383
|
}
|
|
5157
|
-
const baseHome = homeDir ??
|
|
5158
|
-
const primaryWalletPath =
|
|
5159
|
-
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);
|
|
5160
5387
|
const fromPrimary = await readWalletKeyIfPresent(primaryWalletPath);
|
|
5161
5388
|
if (fromPrimary) {
|
|
5162
5389
|
return fromPrimary;
|
|
@@ -5220,9 +5447,9 @@ async function encryptPlaintextFileToAesGcmPath(plaintextPath, dek, outPath, ran
|
|
|
5220
5447
|
}
|
|
5221
5448
|
async function loadOrCreateKek(walletAddress, homeDir) {
|
|
5222
5449
|
const keyPath = resolveWalletKekPath(walletAddress, homeDir);
|
|
5223
|
-
await
|
|
5450
|
+
await mkdir6(dirname6(keyPath), { recursive: true });
|
|
5224
5451
|
try {
|
|
5225
|
-
const existing = await
|
|
5452
|
+
const existing = await readFile4(keyPath);
|
|
5226
5453
|
return { kek: parseStoredAes256Key(existing), keyPath };
|
|
5227
5454
|
} catch (error) {
|
|
5228
5455
|
if (error.code !== "ENOENT") {
|
|
@@ -5230,7 +5457,7 @@ async function loadOrCreateKek(walletAddress, homeDir) {
|
|
|
5230
5457
|
}
|
|
5231
5458
|
}
|
|
5232
5459
|
const generated = randomBytesNode(32);
|
|
5233
|
-
await
|
|
5460
|
+
await writeFile4(keyPath, generated, { mode: 384 });
|
|
5234
5461
|
return { kek: generated, keyPath };
|
|
5235
5462
|
}
|
|
5236
5463
|
async function prepareUploadPayload(archivePath, walletAddress, homeDir) {
|
|
@@ -5242,7 +5469,7 @@ async function prepareUploadPayload(archivePath, walletAddress, homeDir) {
|
|
|
5242
5469
|
const dek = randomBytesNode(32);
|
|
5243
5470
|
const wrappedDek = encryptAesGcm(dek, kek);
|
|
5244
5471
|
if (archiveStat.size >= NODE_FS_MAX_READFILE_BYTES) {
|
|
5245
|
-
const encryptedTempPath =
|
|
5472
|
+
const encryptedTempPath = join10(tmpdir(), `mnemospark-upload-${randomUUID4()}.enc`);
|
|
5246
5473
|
try {
|
|
5247
5474
|
await encryptPlaintextFileToAesGcmPath(archivePath, dek, encryptedTempPath);
|
|
5248
5475
|
const encStat = await stat2(encryptedTempPath);
|
|
@@ -5268,7 +5495,7 @@ async function prepareUploadPayload(archivePath, walletAddress, homeDir) {
|
|
|
5268
5495
|
throw err;
|
|
5269
5496
|
}
|
|
5270
5497
|
}
|
|
5271
|
-
const plaintext = await
|
|
5498
|
+
const plaintext = await readFile4(archivePath);
|
|
5272
5499
|
const encryptedContent = encryptAesGcm(plaintext, dek);
|
|
5273
5500
|
const payloadHash = sha256Buffer(encryptedContent);
|
|
5274
5501
|
const payload = {
|
|
@@ -5513,7 +5740,7 @@ function createInProcessSubagentOrchestrator() {
|
|
|
5513
5740
|
};
|
|
5514
5741
|
return {
|
|
5515
5742
|
dispatch: async (input) => {
|
|
5516
|
-
const sessionId = `agent:mnemospark:subagent:${
|
|
5743
|
+
const sessionId = `agent:mnemospark:subagent:${randomUUID4()}`;
|
|
5517
5744
|
const state = {
|
|
5518
5745
|
terminal: false,
|
|
5519
5746
|
cancelRequested: false,
|
|
@@ -5615,7 +5842,7 @@ function createCloudCommand(options = {}) {
|
|
|
5615
5842
|
createPaymentFetchFn: options.createPaymentFetchFn ?? createPaymentFetch,
|
|
5616
5843
|
fetchImpl: options.fetchImpl ?? fetch,
|
|
5617
5844
|
nowDateFn: options.nowDateFn ?? (() => /* @__PURE__ */ new Date()),
|
|
5618
|
-
idempotencyKeyFn: options.idempotencyKeyFn ??
|
|
5845
|
+
idempotencyKeyFn: options.idempotencyKeyFn ?? randomUUID4,
|
|
5619
5846
|
requestStorageLsFn: options.requestStorageLsFn ?? requestStorageLsViaProxy,
|
|
5620
5847
|
requestStorageDownloadFn: options.requestStorageDownloadFn ?? requestStorageDownloadViaProxy,
|
|
5621
5848
|
requestStorageDeleteFn: options.requestStorageDeleteFn ?? requestStorageDeleteViaProxy,
|
|
@@ -5759,8 +5986,8 @@ async function emitOperationEventBestEffort(eventType, context, homeDir) {
|
|
|
5759
5986
|
}
|
|
5760
5987
|
}
|
|
5761
5988
|
function buildRequestCorrelation(forcedOperationId, forcedTraceId) {
|
|
5762
|
-
const operationId = forcedOperationId?.trim() ||
|
|
5763
|
-
const traceId = forcedTraceId?.trim() ||
|
|
5989
|
+
const operationId = forcedOperationId?.trim() || randomUUID4();
|
|
5990
|
+
const traceId = forcedTraceId?.trim() || randomUUID4();
|
|
5764
5991
|
return { operationId, traceId };
|
|
5765
5992
|
}
|
|
5766
5993
|
function parseTransIdFromPaymentSettleBody(bodyText) {
|
|
@@ -6048,7 +6275,7 @@ ${operation.result_text}` : meta;
|
|
|
6048
6275
|
};
|
|
6049
6276
|
}
|
|
6050
6277
|
if (!isTerminalOperationStatus(operation.status)) {
|
|
6051
|
-
const traceId = operation.trace_id ??
|
|
6278
|
+
const traceId = operation.trace_id ?? randomUUID4();
|
|
6052
6279
|
const cancelRequestedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
6053
6280
|
await datastore.upsertOperation({
|
|
6054
6281
|
operation_id: operation.operation_id,
|
|
@@ -6646,7 +6873,7 @@ operation-id: ${operationId}`,
|
|
|
6646
6873
|
await emitCloudEventBestEffort(
|
|
6647
6874
|
"backup.completed",
|
|
6648
6875
|
{
|
|
6649
|
-
operation_id: executionContext.forcedOperationId?.trim() ||
|
|
6876
|
+
operation_id: executionContext.forcedOperationId?.trim() || randomUUID4(),
|
|
6650
6877
|
object_id: result.objectId,
|
|
6651
6878
|
status: "succeeded",
|
|
6652
6879
|
details: {
|
|
@@ -6692,10 +6919,23 @@ operation-id: ${operationId}`,
|
|
|
6692
6919
|
};
|
|
6693
6920
|
}
|
|
6694
6921
|
}
|
|
6695
|
-
if (parsed.mode === "price-storage") {
|
|
6922
|
+
if (parsed.mode === "price-storage" || parsed.mode === "price-storage-resolve-hash") {
|
|
6923
|
+
let priceStorageRequest;
|
|
6924
|
+
if (parsed.mode === "price-storage-resolve-hash") {
|
|
6925
|
+
const resolved = await resolvePriceStorageHashFromDatastore(
|
|
6926
|
+
datastore,
|
|
6927
|
+
parsed.priceStoragePartial
|
|
6928
|
+
);
|
|
6929
|
+
if (!resolved.ok) {
|
|
6930
|
+
return { text: resolved.message, isError: true };
|
|
6931
|
+
}
|
|
6932
|
+
priceStorageRequest = resolved.request;
|
|
6933
|
+
} else {
|
|
6934
|
+
priceStorageRequest = parsed.priceStorageRequest;
|
|
6935
|
+
}
|
|
6696
6936
|
const correlation = buildRequestCorrelation();
|
|
6697
6937
|
try {
|
|
6698
|
-
const quote = await requestPriceStorageQuote(
|
|
6938
|
+
const quote = await requestPriceStorageQuote(priceStorageRequest, {
|
|
6699
6939
|
...options.proxyQuoteOptions,
|
|
6700
6940
|
correlation
|
|
6701
6941
|
});
|
|
@@ -6753,8 +6993,8 @@ operation-id: ${operationId}`,
|
|
|
6753
6993
|
{
|
|
6754
6994
|
operation_id: correlation.operationId,
|
|
6755
6995
|
trace_id: correlation.traceId,
|
|
6756
|
-
wallet_address:
|
|
6757
|
-
object_id:
|
|
6996
|
+
wallet_address: priceStorageRequest.wallet_address,
|
|
6997
|
+
object_id: priceStorageRequest.object_id,
|
|
6758
6998
|
status: "failed"
|
|
6759
6999
|
},
|
|
6760
7000
|
mnemosparkHomeDir
|
|
@@ -6920,7 +7160,7 @@ operation-id: ${operationId}`,
|
|
|
6920
7160
|
finalizedUploadResponse,
|
|
6921
7161
|
cronStoragePrice,
|
|
6922
7162
|
openClawCronAdapter,
|
|
6923
|
-
mnemosparkHomeDir ??
|
|
7163
|
+
mnemosparkHomeDir ?? homedir7(),
|
|
6924
7164
|
nowDateFn
|
|
6925
7165
|
);
|
|
6926
7166
|
await datastore.upsertObject({
|
|
@@ -7530,12 +7770,12 @@ async function buildWalletExportResponse() {
|
|
|
7530
7770
|
}
|
|
7531
7771
|
|
|
7532
7772
|
// src/cli.ts
|
|
7533
|
-
import { spawn as
|
|
7534
|
-
import { dirname as
|
|
7773
|
+
import { spawn as spawn3 } from "child_process";
|
|
7774
|
+
import { dirname as dirname7, join as join11 } from "path";
|
|
7535
7775
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
7536
|
-
import { mkdir as
|
|
7776
|
+
import { mkdir as mkdir7, readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
|
|
7537
7777
|
import { existsSync as existsSync2 } from "fs";
|
|
7538
|
-
import { homedir as
|
|
7778
|
+
import { homedir as homedir8 } from "os";
|
|
7539
7779
|
function isHexPrivateKey(value) {
|
|
7540
7780
|
return typeof value === "string" && /^0x[0-9a-fA-F]{64}$/.test(value.trim());
|
|
7541
7781
|
}
|
|
@@ -7643,25 +7883,25 @@ function parseArgs(args) {
|
|
|
7643
7883
|
return result;
|
|
7644
7884
|
}
|
|
7645
7885
|
var __filename2 = fileURLToPath2(import.meta.url);
|
|
7646
|
-
var __dirname2 =
|
|
7647
|
-
var PACKAGE_ROOT =
|
|
7886
|
+
var __dirname2 = dirname7(__filename2);
|
|
7887
|
+
var PACKAGE_ROOT = dirname7(__dirname2);
|
|
7648
7888
|
async function ensureDir(path) {
|
|
7649
|
-
await
|
|
7889
|
+
await mkdir7(path, { recursive: true });
|
|
7650
7890
|
}
|
|
7651
7891
|
async function deployExtensionFiles() {
|
|
7652
|
-
const scriptsSource =
|
|
7892
|
+
const scriptsSource = join11(PACKAGE_ROOT, "scripts");
|
|
7653
7893
|
if (!existsSync2(scriptsSource)) return;
|
|
7654
|
-
const mnemoScriptsDir =
|
|
7894
|
+
const mnemoScriptsDir = join11(homedir8(), ".openclaw", "mnemospark", "scripts");
|
|
7655
7895
|
await ensureDir(mnemoScriptsDir);
|
|
7656
|
-
const uninstallSrc =
|
|
7896
|
+
const uninstallSrc = join11(scriptsSource, "uninstall.sh");
|
|
7657
7897
|
if (existsSync2(uninstallSrc)) {
|
|
7658
|
-
const content = await
|
|
7659
|
-
await
|
|
7898
|
+
const content = await readFile5(uninstallSrc);
|
|
7899
|
+
await writeFile5(join11(mnemoScriptsDir, "uninstall.sh"), content, { mode: 493 });
|
|
7660
7900
|
}
|
|
7661
7901
|
}
|
|
7662
7902
|
function isOpenClawAvailable() {
|
|
7663
7903
|
return new Promise((resolve3) => {
|
|
7664
|
-
const child =
|
|
7904
|
+
const child = spawn3("openclaw", ["--version"], {
|
|
7665
7905
|
stdio: "ignore",
|
|
7666
7906
|
shell: true
|
|
7667
7907
|
});
|
|
@@ -7670,13 +7910,13 @@ function isOpenClawAvailable() {
|
|
|
7670
7910
|
});
|
|
7671
7911
|
}
|
|
7672
7912
|
function getOpenClawConfigPath() {
|
|
7673
|
-
const stateDir = process.env.OPENCLAW_STATE_DIR ??
|
|
7674
|
-
return
|
|
7913
|
+
const stateDir = process.env.OPENCLAW_STATE_DIR ?? join11(homedir8(), ".openclaw");
|
|
7914
|
+
return join11(stateDir, "openclaw.json");
|
|
7675
7915
|
}
|
|
7676
7916
|
async function ensureMnemosparkInPluginsAllow() {
|
|
7677
7917
|
const configPath = getOpenClawConfigPath();
|
|
7678
7918
|
try {
|
|
7679
|
-
const raw = await
|
|
7919
|
+
const raw = await readFile5(configPath, "utf-8");
|
|
7680
7920
|
const config = JSON.parse(raw);
|
|
7681
7921
|
if (!config.plugins || typeof config.plugins !== "object") {
|
|
7682
7922
|
config.plugins = {};
|
|
@@ -7688,7 +7928,7 @@ async function ensureMnemosparkInPluginsAllow() {
|
|
|
7688
7928
|
const allow = plugins.allow;
|
|
7689
7929
|
if (!allow.includes("mnemospark")) {
|
|
7690
7930
|
allow.push("mnemospark");
|
|
7691
|
-
await
|
|
7931
|
+
await writeFile5(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
7692
7932
|
console.log("[mnemospark] Added mnemospark to plugins.allow in openclaw.json.");
|
|
7693
7933
|
}
|
|
7694
7934
|
} catch (err) {
|
|
@@ -7701,7 +7941,7 @@ async function promptOrRunOpenClawPluginInstall() {
|
|
|
7701
7941
|
const available = await isOpenClawAvailable();
|
|
7702
7942
|
if (available) {
|
|
7703
7943
|
console.log("\n[mnemospark] Registering plugin with OpenClaw...");
|
|
7704
|
-
const child =
|
|
7944
|
+
const child = spawn3("openclaw", ["plugins", "install", "mnemospark"], {
|
|
7705
7945
|
stdio: "inherit",
|
|
7706
7946
|
shell: true
|
|
7707
7947
|
});
|
|
@@ -7723,7 +7963,7 @@ async function promptOrRunOpenClawPluginInstall() {
|
|
|
7723
7963
|
}
|
|
7724
7964
|
async function readLegacyWalletIfPresent() {
|
|
7725
7965
|
try {
|
|
7726
|
-
const key = (await
|
|
7966
|
+
const key = (await readFile5(LEGACY_WALLET_FILE, "utf-8")).trim();
|
|
7727
7967
|
return isHexPrivateKey(key) ? key : null;
|
|
7728
7968
|
} catch (error) {
|
|
7729
7969
|
if (error.code === "ENOENT") {
|
|
@@ -7733,9 +7973,9 @@ async function readLegacyWalletIfPresent() {
|
|
|
7733
7973
|
}
|
|
7734
7974
|
}
|
|
7735
7975
|
async function writeMnemosparkWallet(key) {
|
|
7736
|
-
const dir =
|
|
7976
|
+
const dir = dirname7(WALLET_FILE);
|
|
7737
7977
|
await ensureDir(dir);
|
|
7738
|
-
await
|
|
7978
|
+
await writeFile5(WALLET_FILE, `${key}
|
|
7739
7979
|
`, { mode: 384 });
|
|
7740
7980
|
}
|
|
7741
7981
|
async function promptReuseLegacyWallet() {
|