mnemospark 2026.4.6 → 2026.4.8

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 CHANGED
@@ -162,7 +162,8 @@ Optional unless noted. All names use the `MNEMOSPARK_` prefix.
162
162
  | `MNEMOSPARK_SQLITE_STRICT` | Set to `1` so certain SQLite consistency checks (e.g. friendly-name verification after upload) throw instead of warning. |
163
163
  | `MNEMOSPARK_PROXY_VERBOSE_404` | When `1`, `true`, or `yes`, the local HTTP proxy includes a `message` field on **404** responses describing supported paths. Default (unset) is a generic JSON body `{ "error": "Not found" }` only (reduces reconnaissance). |
164
164
  | `MNEMOSPARK_CRON_AGENT_ID` | OpenClaw agent id used for the monthly renewal cron (default `mnemospark-renewal`). |
165
- | `MNEMOSPARK_CRON_NODE_BIN` | Absolute path to `node` for renewal cron exec (default `/usr/bin/node`). |
165
+ | `MNEMOSPARK_AGENT_ID` | OpenClaw agent id for interactive wallet/cloud CLI via the dedicated-agent runbook (default `mnemospark`). Distinct from `MNEMOSPARK_CRON_AGENT_ID`. |
166
+ | `MNEMOSPARK_CRON_NODE_BIN` | Absolute path to `node` for dedicated-agent exec allowlists and renewal cron payloads (default `/usr/bin/node`). |
166
167
  | `MNEMOSPARK_DISABLE_OPENCLAW_PREREQ` | Set to `1` to skip automatic runbook application everywhere it runs (plugin load, CLI install/update; for advanced debugging only). |
167
168
 
168
169
  ---
@@ -179,7 +180,12 @@ Optional unless noted. All names use the `MNEMOSPARK_` prefix.
179
180
 
180
181
  ## mnemospark Exec Approvals Runbook
181
182
 
182
- On **OpenClaw 2026.4.x**, the **Mnemospark Renewal Agent Runbook** is applied when you install or update mnemospark (including `npx mnemospark install`, `npx mnemospark update`, `openclaw plugins install`, and when the gateway loads the plugin): it ensures a dedicated agent (`mnemospark-renewal` by default) with `tools.deny: ["subagents"]` and `tools.exec.ask: "off"`, updates `~/.openclaw/exec-approvals.json` so `/usr/bin/node` is allowlisted for that agent, and runs `openclaw config validate`. OpenClaw restarts the gateway when a plugin is installed or updated; mnemospark does not call `openclaw gateway restart` itself. After a **successful upload**, mnemospark registers the monthly renewal cron only (`--no-deliver`, `--agent`, and a `Command: /usr/bin/node …/dist/cli.js cloud payment-settle --renewal …` message). Override paths with `MNEMOSPARK_CRON_AGENT_ID` and `MNEMOSPARK_CRON_NODE_BIN` if your system differs.
183
+ On **OpenClaw 2026.4.x**, mnemospark applies **two** dedicated-agent runbooks when you install or update (including `npx mnemospark install`, `npx mnemospark update`, `openclaw plugins install`, and when the gateway loads the plugin):
184
+
185
+ 1. **`mnemospark-renewal`** (default; override `MNEMOSPARK_CRON_AGENT_ID`) — monthly storage renewal cron: `tools.deny: ["subagents"]`, `tools.exec.ask: "off"`, and `/usr/bin/node` allowlisted for that agent in `~/.openclaw/exec-approvals.json`.
186
+ 2. **`mnemospark`** (default; override `MNEMOSPARK_AGENT_ID`) — interactive wallet and cloud CLI work: same tool policy and its **own** `/usr/bin/node` allowlist entry under that agent id.
187
+
188
+ The plugin merges both into `agents.list` via `openclaw config set` + `openclaw config validate`. OpenClaw restarts the gateway when a plugin is installed or updated; mnemospark does not call `openclaw gateway restart` itself. After a **successful upload**, mnemospark registers the monthly renewal cron only (`--no-deliver`, `--agent`, and a `Command: /usr/bin/node …/dist/cli.js cloud payment-settle --renewal …` message) against the renewal agent id. For interactive automation, route through the general agent (see bundled skill `skills/mnemospark/references/openclaw-routing.md`). Override the node path with `MNEMOSPARK_CRON_NODE_BIN` if your system differs.
183
189
 
184
190
  ---
185
191
 
@@ -189,7 +195,8 @@ On **OpenClaw 2026.4.x**, the **Mnemospark Renewal Agent Runbook** is applied wh
189
195
  - **402 payment required**: expected in challenge flow; ensure client retries with payment authorization.
190
196
  - **Upload/storage backend errors**: verify cloud permissions (e.g. bucket access + IAM role rights).
191
197
  - **Command not recognized**: confirm plugin installed and gateway restarted.
192
- - **Renewal cron / exec failures after upload**: ensure mnemospark was installed or updated through the normal path so the runbook ran (gateway load, `npx mnemospark install`, or `openclaw plugins install`). If the gateway never loaded the plugin, run install again or restart the gateway.
198
+ - **Renewal cron / exec failures after upload**: ensure mnemospark was installed or updated through the normal path so both dedicated-agent runbooks ran (gateway load, `npx mnemospark install`, or `openclaw plugins install`). If the gateway never loaded the plugin, run install again or restart the gateway.
199
+ - **Interactive Mnemospark exec denied on main**: use a dedicated `mnemospark` agent and route with `openclaw agent --agent mnemospark …` (see skill reference `openclaw-routing.md`); renewal-only setup does not cover general plugin usage.
193
200
  - **One-step operation correlation**: run `./skills/mnemospark/scripts/debug-operation.sh <operation-id>` (or omit ID to use latest).
194
201
 
195
202
  ---
package/dist/cli.js CHANGED
@@ -4352,16 +4352,21 @@ import { homedir as homedir6 } from "os";
4352
4352
  import { dirname as dirname5, join as join9 } from "path";
4353
4353
  import { randomUUID as randomUUID3 } from "crypto";
4354
4354
  var DEFAULT_RENEWAL_AGENT_ID = "mnemospark-renewal";
4355
+ var DEFAULT_MNEMOSPARK_AGENT_ID = "mnemospark";
4355
4356
  var RENEWAL_NODE_ALLOWLIST_ID = "node-usr-bin-node";
4356
4357
  function getRenewalAgentId() {
4357
4358
  const fromEnv = process.env.MNEMOSPARK_CRON_AGENT_ID?.trim();
4358
4359
  return fromEnv && fromEnv.length > 0 ? fromEnv : DEFAULT_RENEWAL_AGENT_ID;
4359
4360
  }
4361
+ function getMnemosparkAgentId() {
4362
+ const fromEnv = process.env.MNEMOSPARK_AGENT_ID?.trim();
4363
+ return fromEnv && fromEnv.length > 0 ? fromEnv : DEFAULT_MNEMOSPARK_AGENT_ID;
4364
+ }
4360
4365
  function getRenewalNodeBinary() {
4361
4366
  const fromEnv = process.env.MNEMOSPARK_CRON_NODE_BIN?.trim();
4362
4367
  return fromEnv && fromEnv.length > 0 ? fromEnv : "/usr/bin/node";
4363
4368
  }
4364
- function runbookRenewalAgentEntry(agentId = getRenewalAgentId()) {
4369
+ function runbookDedicatedAgentEntry(agentId) {
4365
4370
  return {
4366
4371
  id: agentId,
4367
4372
  tools: {
@@ -4370,10 +4375,13 @@ function runbookRenewalAgentEntry(agentId = getRenewalAgentId()) {
4370
4375
  }
4371
4376
  };
4372
4377
  }
4378
+ function runbookRenewalAgentEntry(agentId = getRenewalAgentId()) {
4379
+ return runbookDedicatedAgentEntry(agentId);
4380
+ }
4373
4381
  function isRecord(value) {
4374
4382
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
4375
4383
  }
4376
- function renewalAgentEntrySatisfied(existing, desired) {
4384
+ function dedicatedAgentEntrySatisfied(existing, desired) {
4377
4385
  if (!isRecord(existing)) {
4378
4386
  return false;
4379
4387
  }
@@ -4400,7 +4408,7 @@ function mergeRenewalAgentIntoAgentsList(list, desired) {
4400
4408
  if (idx === -1) {
4401
4409
  return { list: [...arr, desired], changed: true };
4402
4410
  }
4403
- if (renewalAgentEntrySatisfied(arr[idx], desired)) {
4411
+ if (dedicatedAgentEntrySatisfied(arr[idx], desired)) {
4404
4412
  return { list: arr, changed: false };
4405
4413
  }
4406
4414
  const next = [...arr];
@@ -4445,8 +4453,10 @@ async function ensureOpenClawRenewalPrerequisites(options = {}) {
4445
4453
  return;
4446
4454
  }
4447
4455
  const homeDir = options.homeDir ?? homedir6();
4448
- const agentId = getRenewalAgentId();
4449
- const desired = runbookRenewalAgentEntry(agentId);
4456
+ const renewalId = getRenewalAgentId();
4457
+ const pluginAgentId = getMnemosparkAgentId();
4458
+ const desiredRenewal = runbookRenewalAgentEntry(renewalId);
4459
+ const desiredPlugin = runbookDedicatedAgentEntry(pluginAgentId);
4450
4460
  const nodeBinary = getRenewalNodeBinary();
4451
4461
  const configPath = await resolveOpenClawConfigFilePath(homeDir);
4452
4462
  let configRaw = "{}";
@@ -4462,14 +4472,18 @@ async function ensureOpenClawRenewalPrerequisites(options = {}) {
4462
4472
  parsed = JSON.parse(configRaw);
4463
4473
  } catch {
4464
4474
  throw new Error(
4465
- `openclaw.json at ${configPath} is not valid JSON; fix or remove it before applying renewal prerequisites.`
4475
+ `openclaw.json at ${configPath} is not valid JSON; fix or remove it before applying mnemospark OpenClaw prerequisites.`
4466
4476
  );
4467
4477
  }
4468
4478
  const agents = isRecord(parsed.agents) ? parsed.agents : {};
4469
- const { list: mergedList, changed: agentChanged } = mergeRenewalAgentIntoAgentsList(
4470
- agents.list,
4471
- desired
4472
- );
4479
+ let mergedList = [];
4480
+ let agentChanged = false;
4481
+ const afterRenewal = mergeRenewalAgentIntoAgentsList(agents.list, desiredRenewal);
4482
+ mergedList = afterRenewal.list;
4483
+ agentChanged = afterRenewal.changed;
4484
+ const afterPlugin = mergeRenewalAgentIntoAgentsList(mergedList, desiredPlugin);
4485
+ mergedList = afterPlugin.list;
4486
+ agentChanged = agentChanged || afterPlugin.changed;
4473
4487
  if (agentChanged) {
4474
4488
  const listJson = JSON.stringify(mergedList);
4475
4489
  await runOpenClawCli(["config", "set", "agents.list", listJson, "--strict-json"], homeDir);
@@ -4485,11 +4499,13 @@ async function ensureOpenClawRenewalPrerequisites(options = {}) {
4485
4499
  throw err;
4486
4500
  }
4487
4501
  }
4488
- const { doc: mergedExec, changed: execChanged } = mergeExecApprovalsAllowlist(
4489
- execDoc,
4490
- agentId,
4491
- nodeBinary
4492
- );
4502
+ let mergedExec = execDoc;
4503
+ let execChanged = false;
4504
+ for (const id of [renewalId, pluginAgentId]) {
4505
+ const { doc, changed } = mergeExecApprovalsAllowlist(mergedExec, id, nodeBinary);
4506
+ mergedExec = doc;
4507
+ execChanged = execChanged || changed;
4508
+ }
4493
4509
  if (execChanged) {
4494
4510
  await writeFileAtomic(execPath, `${JSON.stringify(mergedExec, null, 2)}
4495
4511
  `);
@@ -8036,7 +8052,7 @@ async function promptOrRunOpenClawPluginInstall() {
8036
8052
  await ensureOpenClawRenewalPrerequisites();
8037
8053
  } catch (err) {
8038
8054
  console.warn(
8039
- "[mnemospark] Renewal prerequisites:",
8055
+ "[mnemospark] OpenClaw prerequisites:",
8040
8056
  err instanceof Error ? err.message : String(err)
8041
8057
  );
8042
8058
  }
@@ -8143,7 +8159,7 @@ async function runUpdate() {
8143
8159
  await ensureOpenClawRenewalPrerequisites();
8144
8160
  } catch (err) {
8145
8161
  console.warn(
8146
- "[mnemospark] Renewal prerequisites:",
8162
+ "[mnemospark] OpenClaw prerequisites:",
8147
8163
  err instanceof Error ? err.message : String(err)
8148
8164
  );
8149
8165
  }