@moltbankhq/openclaw 0.1.0 → 0.1.2
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 +98 -0
- package/index.ts +61 -105
- package/openclaw.plugin.json +1 -1
- package/package.json +2 -2
package/README.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# @moltbankhq/openclaw
|
|
2
|
+
|
|
3
|
+
OpenClaw plugin for [MoltBank](https://moltbank.bot) — stablecoin treasury controls, approvals, and audit trails for agent fleets.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
openclaw plugins install @moltbankhq/openclaw
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Direct `npm install` can be useful to acquire the package, but by itself it does not complete OpenClaw plugin registration or setup.
|
|
12
|
+
|
|
13
|
+
## What it does
|
|
14
|
+
|
|
15
|
+
This plugin connects your OpenClaw agent to MoltBank's stablecoin treasury infrastructure. On install, it:
|
|
16
|
+
|
|
17
|
+
- Downloads and configures the MoltBank skill (SKILL.md + scripts)
|
|
18
|
+
- Installs and registers [mcporter](https://www.npmjs.com/package/mcporter) for MCP server connectivity
|
|
19
|
+
- Handles OAuth device-code authentication to link your agent to your MoltBank account
|
|
20
|
+
- Configures sandbox (Docker) or host mode automatically based on your OpenClaw setup
|
|
21
|
+
- Injects required environment variables (`MOLTBANK`, `SIGNER`, `ACTIVE_ORG_OVERRIDE`)
|
|
22
|
+
|
|
23
|
+
Once set up, your agent can manage treasury operations, set per-agent spending limits, handle x402 payments, and interact with MoltBank's MCP server — all within OpenClaw.
|
|
24
|
+
|
|
25
|
+
## Setup
|
|
26
|
+
|
|
27
|
+
After installing, run:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
openclaw moltbank setup
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The plugin will guide you through linking your MoltBank account via browser-based OAuth. Once approved, setup finalizes automatically.
|
|
34
|
+
|
|
35
|
+
## CLI Commands
|
|
36
|
+
|
|
37
|
+
| Command | Description |
|
|
38
|
+
|---------|-------------|
|
|
39
|
+
| `openclaw moltbank setup` | Run full setup (nonblocking auth) |
|
|
40
|
+
| `openclaw moltbank setup-blocking` | Setup and wait for OAuth approval |
|
|
41
|
+
| `openclaw moltbank auth-status` | Check current auth state |
|
|
42
|
+
| `openclaw moltbank sandbox-setup` | Reconfigure sandbox Docker settings |
|
|
43
|
+
| `openclaw moltbank inject-key` | Re-inject env vars from credentials |
|
|
44
|
+
| `openclaw moltbank register` | Re-register mcporter MCP server |
|
|
45
|
+
|
|
46
|
+
## Configuration
|
|
47
|
+
|
|
48
|
+
Optional config in your `openclaw.json`:
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"plugins": {
|
|
53
|
+
"entries": {
|
|
54
|
+
"moltbank": {
|
|
55
|
+
"config": {
|
|
56
|
+
"appBaseUrl": "https://app.moltbank.bot",
|
|
57
|
+
"skillName": "MoltBank"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Environment Variables
|
|
66
|
+
|
|
67
|
+
| Variable | Description |
|
|
68
|
+
|----------|-------------|
|
|
69
|
+
| `APP_BASE_URL` | MoltBank deployment URL (default: `https://app.moltbank.bot`) |
|
|
70
|
+
| `MOLTBANK_SKILL_NAME` | Override skill folder name (default: `MoltBank`) |
|
|
71
|
+
| `MOLTBANK_CREDENTIALS_PATH` | Custom credentials file path |
|
|
72
|
+
| `MOLTBANK_SETUP_AUTH_WAIT_MODE` | `blocking` or `nonblocking` (default: `nonblocking`) |
|
|
73
|
+
|
|
74
|
+
## Capabilities
|
|
75
|
+
|
|
76
|
+
The MoltBank skill gives your agent access to:
|
|
77
|
+
|
|
78
|
+
- **Treasury management** — balances, transfers, account operations
|
|
79
|
+
- **Per-agent spending limits** — transaction, daily, and weekly caps
|
|
80
|
+
- **Approval workflows** — human-in-the-loop for spend above thresholds
|
|
81
|
+
- **x402 payments** — agent-to-agent payments via the x402 protocol
|
|
82
|
+
- **Audit trails** — full visibility into which agent spent what, when, and why
|
|
83
|
+
|
|
84
|
+
## Requirements
|
|
85
|
+
|
|
86
|
+
- OpenClaw v2026.3+
|
|
87
|
+
- Node.js 22+
|
|
88
|
+
- Docker (if using sandbox mode)
|
|
89
|
+
|
|
90
|
+
## Links
|
|
91
|
+
|
|
92
|
+
- [MoltBank](https://moltbank.bot)
|
|
93
|
+
- [Documentation](https://app.moltbank.bot)
|
|
94
|
+
- [GitHub](https://github.com/moltbankhq/openclaw-plugin)
|
|
95
|
+
|
|
96
|
+
## License
|
|
97
|
+
|
|
98
|
+
ISC
|
package/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { execSync, spawn } from 'child_process';
|
|
2
|
-
import { chmodSync, existsSync, mkdirSync, readFileSync,
|
|
2
|
+
import { chmodSync, existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from 'fs';
|
|
3
3
|
import { join, dirname } from 'path';
|
|
4
4
|
import { homedir } from 'os';
|
|
5
5
|
const IS_WIN = process.platform === 'win32';
|
|
@@ -276,43 +276,34 @@ function ensureWrapperExecutable(skillDir: string, api: LoggerApi): void {
|
|
|
276
276
|
// ─── skill install ───────────────────────────────────────────────────────────
|
|
277
277
|
|
|
278
278
|
const SKILL_FILES = [
|
|
279
|
+
'README.md',
|
|
279
280
|
'skill.md',
|
|
280
|
-
'setup.md',
|
|
281
|
-
'onboarding.md',
|
|
282
|
-
'multi-org.md',
|
|
283
|
-
'tools-reference.md',
|
|
284
|
-
'x402-workflow.md',
|
|
285
|
-
'heartbeat.md',
|
|
286
|
-
'rules.md',
|
|
287
281
|
'skill.json',
|
|
288
|
-
'
|
|
289
|
-
'
|
|
290
|
-
'
|
|
291
|
-
'
|
|
292
|
-
'openclaw-
|
|
293
|
-
'
|
|
294
|
-
'
|
|
282
|
+
'install.sh',
|
|
283
|
+
'assets/mcporter.json',
|
|
284
|
+
'references/heartbeat.md',
|
|
285
|
+
'references/onboarding.md',
|
|
286
|
+
'references/openclaw-signer-eoa.md',
|
|
287
|
+
'references/rules.md',
|
|
288
|
+
'references/setup.md',
|
|
289
|
+
'references/tools-reference.md',
|
|
290
|
+
'references/x402-workflow.md',
|
|
295
291
|
'scripts/openclaw-runtime-config.mjs',
|
|
296
292
|
'scripts/request-oauth-device-code.mjs',
|
|
297
293
|
'scripts/init-openclaw-signer.mjs',
|
|
298
|
-
'scripts/init-openclaw-solana-signer.mjs',
|
|
299
|
-
'scripts/bootstrap-openclaw-pumpfun-wallet.mjs',
|
|
300
294
|
'scripts/inspect-x402-requirements.mjs',
|
|
301
|
-
'scripts/inspect-solana-wallet.mjs',
|
|
302
|
-
'scripts/inspect-polygon-wallet.mjs',
|
|
303
|
-
'scripts/quote-solana-budget.mjs',
|
|
304
|
-
'scripts/polymarket-execute-lifi-tx.mjs',
|
|
305
|
-
'scripts/polymarket-signer-to-safe.mjs',
|
|
306
295
|
'scripts/poll-oauth-token.mjs',
|
|
307
296
|
'scripts/export-api-key.mjs',
|
|
308
|
-
'scripts/fetch-openrouter-intent.mjs',
|
|
309
297
|
'scripts/x402-pay-and-confirm.mjs',
|
|
310
|
-
'scripts/
|
|
298
|
+
'scripts/setup-sandbox.sh',
|
|
311
299
|
'scripts/moltbank.sh',
|
|
312
|
-
'scripts/moltbank.ps1'
|
|
313
|
-
'scripts/polymarket-service.mjs'
|
|
300
|
+
'scripts/moltbank.ps1'
|
|
314
301
|
];
|
|
315
302
|
|
|
303
|
+
function hasRequiredSkillFiles(skillDir: string): boolean {
|
|
304
|
+
return SKILL_FILES.every((file) => existsSync(join(skillDir, file)));
|
|
305
|
+
}
|
|
306
|
+
|
|
316
307
|
function ensureSkillInstalled(
|
|
317
308
|
skillDir: string,
|
|
318
309
|
appBaseUrl: string,
|
|
@@ -321,12 +312,21 @@ function ensureSkillInstalled(
|
|
|
321
312
|
mode: 'sandbox' | 'host' = 'sandbox'
|
|
322
313
|
) {
|
|
323
314
|
const successFlag = join(skillDir, '.install_success');
|
|
324
|
-
if (existsSync(successFlag)) {
|
|
315
|
+
if (existsSync(successFlag) && hasRequiredSkillFiles(skillDir)) {
|
|
325
316
|
ensureWrapperExecutable(skillDir, api);
|
|
326
317
|
api.logger.info('[moltbank] ✓ skill already installed at ' + skillDir);
|
|
327
318
|
return true;
|
|
328
319
|
}
|
|
329
320
|
|
|
321
|
+
if (existsSync(successFlag)) {
|
|
322
|
+
api.logger.warn('[moltbank] existing skill install is stale or incomplete — reinstalling current bundle');
|
|
323
|
+
try {
|
|
324
|
+
unlinkSync(successFlag);
|
|
325
|
+
} catch {
|
|
326
|
+
// ignore
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
330
|
api.logger.info(`[moltbank] installing skill '${skillName}' to ${skillDir} (mode: ${mode})`);
|
|
331
331
|
mkdirSync(skillDir, { recursive: true });
|
|
332
332
|
|
|
@@ -350,66 +350,32 @@ function ensureSkillInstalled(
|
|
|
350
350
|
function ensureSkillFilesUppercase(skillDir: string, api: LoggerApi) {
|
|
351
351
|
const lower = join(skillDir, 'skill.md');
|
|
352
352
|
const upper = join(skillDir, 'SKILL.md');
|
|
353
|
-
if (existsSync(
|
|
354
|
-
api.logger.info('[moltbank] ✓
|
|
353
|
+
if (existsSync(lower)) {
|
|
354
|
+
api.logger.info('[moltbank] ✓ skill entrypoint present (skill.md)');
|
|
355
355
|
return;
|
|
356
356
|
}
|
|
357
|
-
if (existsSync(
|
|
358
|
-
|
|
359
|
-
api.logger.info('[moltbank] ✓ renamed skill.md → SKILL.md');
|
|
357
|
+
if (existsSync(upper)) {
|
|
358
|
+
api.logger.info('[moltbank] ✓ skill entrypoint present (SKILL.md)');
|
|
360
359
|
} else {
|
|
361
360
|
api.logger.warn('[moltbank] ✗ neither skill.md nor SKILL.md found');
|
|
362
361
|
}
|
|
363
362
|
}
|
|
364
363
|
|
|
365
364
|
function fixSkillFrontmatter(skillDir: string, skillName: string, api: LoggerApi) {
|
|
366
|
-
const skillFile = join(skillDir, 'SKILL.md');
|
|
365
|
+
const skillFile = existsSync(join(skillDir, 'skill.md')) ? join(skillDir, 'skill.md') : join(skillDir, 'SKILL.md');
|
|
367
366
|
if (!existsSync(skillFile)) {
|
|
368
|
-
api.logger.warn('[moltbank] ✗
|
|
367
|
+
api.logger.warn('[moltbank] ✗ skill entrypoint not found — skipping frontmatter validation');
|
|
369
368
|
return;
|
|
370
369
|
}
|
|
371
370
|
|
|
372
371
|
const content = readFileSync(skillFile, 'utf8').replace(/\r\n/g, '\n');
|
|
373
372
|
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
374
373
|
if (!frontmatterMatch) {
|
|
375
|
-
api.logger.warn('[moltbank] ✗ no frontmatter in
|
|
374
|
+
api.logger.warn('[moltbank] ✗ no frontmatter in skill entrypoint');
|
|
376
375
|
return;
|
|
377
376
|
}
|
|
378
377
|
|
|
379
|
-
|
|
380
|
-
const newFrontmatter = `---
|
|
381
|
-
name: ${skillName}
|
|
382
|
-
version: 1.5.3
|
|
383
|
-
description: MCP skill for MoltBank business banking workflows (treasury, approvals, allowances, x402, OpenRouter, Polymarket, and Pump.Fun).
|
|
384
|
-
homepage: \${APP_BASE_URL:-https://app.moltbank.bot}
|
|
385
|
-
metadata:
|
|
386
|
-
category: finance
|
|
387
|
-
api_base: \${APP_BASE_URL:-https://app.moltbank.bot}/api/mcp
|
|
388
|
-
install_script: \${APP_BASE_URL:-https://app.moltbank.bot}/install.sh
|
|
389
|
-
openclaw:
|
|
390
|
-
requires:
|
|
391
|
-
bins:
|
|
392
|
-
${binsYaml}
|
|
393
|
-
npm:
|
|
394
|
-
- '@x402/fetch@^2.3.0'
|
|
395
|
-
- '@x402/evm@^2.3.1'
|
|
396
|
-
- 'viem@^2.46.0'
|
|
397
|
-
- '@polymarket/clob-client'
|
|
398
|
-
- 'ethers@5'
|
|
399
|
-
- '@solana/web3.js@^1.98.4'
|
|
400
|
-
- 'bs58@^6.0.0'
|
|
401
|
-
primaryEnv: MOLTBANK
|
|
402
|
-
---`;
|
|
403
|
-
|
|
404
|
-
const body = content.slice(frontmatterMatch[0].length);
|
|
405
|
-
const fixed = newFrontmatter + body;
|
|
406
|
-
|
|
407
|
-
if (fixed !== content) {
|
|
408
|
-
writeFileSync(skillFile, fixed, 'utf8');
|
|
409
|
-
api.logger.info(`[moltbank] ✓ SKILL.md frontmatter fixed → name: ${skillName}`);
|
|
410
|
-
} else {
|
|
411
|
-
api.logger.info('[moltbank] ✓ SKILL.md frontmatter already correct');
|
|
412
|
-
}
|
|
378
|
+
api.logger.info(`[moltbank] ✓ skill frontmatter retained as authored (${skillName})`);
|
|
413
379
|
}
|
|
414
380
|
|
|
415
381
|
function ensureSkillPermissions(skillDir: string, api: LoggerApi) {
|
|
@@ -418,8 +384,9 @@ function ensureSkillPermissions(skillDir: string, api: LoggerApi) {
|
|
|
418
384
|
return;
|
|
419
385
|
}
|
|
420
386
|
|
|
421
|
-
const
|
|
422
|
-
const configFile = join(skillDir, '
|
|
387
|
+
const assetsDir = join(skillDir, 'assets');
|
|
388
|
+
const configFile = join(skillDir, 'assets', 'mcporter.json');
|
|
389
|
+
const referencesDir = join(skillDir, 'references');
|
|
423
390
|
const scriptsDir = join(skillDir, 'scripts');
|
|
424
391
|
|
|
425
392
|
const user = run('whoami', { silent: true }).stdout;
|
|
@@ -428,9 +395,9 @@ function ensureSkillPermissions(skillDir: string, api: LoggerApi) {
|
|
|
428
395
|
api.logger.info(`[moltbank] ✓ ownership corrected to ${user}`);
|
|
429
396
|
}
|
|
430
397
|
|
|
431
|
-
if (existsSync(
|
|
432
|
-
run(`chmod 777 "${
|
|
433
|
-
api.logger.info('[moltbank] ✓
|
|
398
|
+
if (existsSync(assetsDir)) {
|
|
399
|
+
run(`chmod 777 "${assetsDir}"`, { silent: true });
|
|
400
|
+
api.logger.info('[moltbank] ✓ assets/ permissions → 777');
|
|
434
401
|
}
|
|
435
402
|
if (existsSync(configFile)) {
|
|
436
403
|
run(`chmod 666 "${configFile}"`, { silent: true });
|
|
@@ -439,15 +406,20 @@ function ensureSkillPermissions(skillDir: string, api: LoggerApi) {
|
|
|
439
406
|
if (existsSync(scriptsDir)) {
|
|
440
407
|
run(`chmod -R 755 "${scriptsDir}"`, { silent: true });
|
|
441
408
|
api.logger.info('[moltbank] ✓ scripts/ permissions → 755');
|
|
442
|
-
run(`find "${scriptsDir}" -type f
|
|
409
|
+
run(`find "${scriptsDir}" -type f -exec sed -i 's/\r$//' {} +`, {
|
|
443
410
|
silent: true
|
|
444
411
|
});
|
|
445
412
|
api.logger.info('[moltbank] ✓ scripts/ line endings normalized (CRLF → LF)');
|
|
446
413
|
}
|
|
447
414
|
|
|
448
415
|
if (existsSync(skillDir)) {
|
|
449
|
-
run(`find "${skillDir}" -maxdepth 1 -name "*.md"
|
|
450
|
-
|
|
416
|
+
run(`find "${skillDir}" -maxdepth 1 -type f -name "*.md" -exec sed -i 's/\r$//' {} +`, { silent: true });
|
|
417
|
+
}
|
|
418
|
+
if (existsSync(referencesDir)) {
|
|
419
|
+
run(`find "${referencesDir}" -maxdepth 1 -type f -name "*.md" -exec sed -i 's/\r$//' {} +`, { silent: true });
|
|
420
|
+
}
|
|
421
|
+
if (existsSync(skillDir) || existsSync(referencesDir)) {
|
|
422
|
+
api.logger.info('[moltbank] ✓ markdown line endings normalized (CRLF → LF)');
|
|
451
423
|
}
|
|
452
424
|
}
|
|
453
425
|
|
|
@@ -464,28 +436,12 @@ function ensureNpmDeps(skillDir: string, api: LoggerApi, mode: 'sandbox' | 'host
|
|
|
464
436
|
dependencies: {
|
|
465
437
|
'@x402/fetch': '^2.3.0',
|
|
466
438
|
'@x402/evm': '^2.3.1',
|
|
467
|
-
viem: '^2.46.0'
|
|
468
|
-
'@polymarket/clob-client': 'latest',
|
|
469
|
-
ethers: '^5.8.0',
|
|
470
|
-
'@solana/web3.js': '^1.98.4',
|
|
471
|
-
bs58: '^6.0.0'
|
|
439
|
+
viem: '^2.46.0'
|
|
472
440
|
}
|
|
473
441
|
};
|
|
474
442
|
writeFileSync(pkgPath, JSON.stringify(fallbackPkg, null, 2) + '\n', 'utf8');
|
|
475
443
|
api.logger.warn('[moltbank] package.json not found — created fallback package.json for skill runtime deps');
|
|
476
444
|
}
|
|
477
|
-
try {
|
|
478
|
-
const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
|
|
479
|
-
pkg.dependencies = pkg.dependencies ?? {};
|
|
480
|
-
const cur = String(pkg.dependencies['@polymarket/clob-client'] ?? '').trim();
|
|
481
|
-
if (!cur || cur === '^6.0.0') {
|
|
482
|
-
pkg.dependencies['@polymarket/clob-client'] = 'latest';
|
|
483
|
-
writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf8');
|
|
484
|
-
api.logger.info('[moltbank] normalized package.json: @polymarket/clob-client -> latest');
|
|
485
|
-
}
|
|
486
|
-
} catch (e) {
|
|
487
|
-
api.logger.warn('[moltbank] could not normalize package.json deps: ' + String(e));
|
|
488
|
-
}
|
|
489
445
|
api.logger.info('[moltbank] installing npm deps...');
|
|
490
446
|
if (mode === 'sandbox') {
|
|
491
447
|
const result = run('npm install --ignore-scripts', { cwd: skillDir });
|
|
@@ -927,13 +883,13 @@ function printAuthStatus(skillDir: string, appBaseUrl: string, api: LoggerApi):
|
|
|
927
883
|
}
|
|
928
884
|
|
|
929
885
|
function ensureMcporterConfig(skillDir: string, appBaseUrl: string, api: LoggerApi) {
|
|
930
|
-
const cfgPath = join(skillDir, '
|
|
931
|
-
mkdirSync(join(skillDir, '
|
|
886
|
+
const cfgPath = join(skillDir, 'assets', 'mcporter.json');
|
|
887
|
+
mkdirSync(join(skillDir, 'assets'), { recursive: true });
|
|
932
888
|
|
|
933
889
|
const cfg = {
|
|
934
890
|
mcpServers: {
|
|
935
891
|
MoltBank: {
|
|
936
|
-
description: 'MoltBank stablecoin
|
|
892
|
+
description: 'MoltBank stablecoin treasury MCP server powered by Fondu',
|
|
937
893
|
transport: 'sse',
|
|
938
894
|
url: `${appBaseUrl}/api/mcp`,
|
|
939
895
|
headers: {
|
|
@@ -965,7 +921,7 @@ function ensureMcporterConfig(skillDir: string, appBaseUrl: string, api: LoggerA
|
|
|
965
921
|
`--transport sse ` +
|
|
966
922
|
`--header "Authorization=Bearer \${MOLTBANK}" ` +
|
|
967
923
|
`--header "Content-Type=application/json" ` +
|
|
968
|
-
`--description "MoltBank stablecoin
|
|
924
|
+
`--description "MoltBank stablecoin treasury MCP server powered by Fondu" ` +
|
|
969
925
|
`--scope home`;
|
|
970
926
|
|
|
971
927
|
const result = run(addCmd, { silent: false });
|
|
@@ -1040,7 +996,7 @@ function injectSandboxEnv(skillDir: string, api: LoggerApi): boolean {
|
|
|
1040
996
|
});
|
|
1041
997
|
if (!initResult.ok) {
|
|
1042
998
|
api.logger.warn('[moltbank] ✗ could not generate EOA signer: ' + initResult.stderr);
|
|
1043
|
-
api.logger.warn('[moltbank] agent will generate signer on first x402
|
|
999
|
+
api.logger.warn('[moltbank] agent will generate signer on first x402 use');
|
|
1044
1000
|
} else {
|
|
1045
1001
|
const freshCreds = JSON.parse(readFileSync(credsPath, 'utf8')) as CredentialsFile;
|
|
1046
1002
|
const freshOrg = freshCreds.organizations?.find((o: CredentialsOrganization) => o.name === activeOrg);
|
|
@@ -1100,7 +1056,7 @@ function configureSandbox(api: LoggerApi): boolean {
|
|
|
1100
1056
|
'update-alternatives --set node $NODE22_BIN 2>/dev/null || true && ' +
|
|
1101
1057
|
'node -v && npm -v && ' +
|
|
1102
1058
|
"echo '[moltbank:sandbox] [5/7] installing npm global deps (mcporter + sdk libs)...' && " +
|
|
1103
|
-
'npm install -g mcporter @x402/fetch@2.3.0 @x402/evm@2.3.1 viem@2.46.0
|
|
1059
|
+
'npm install -g mcporter @x402/fetch@2.3.0 @x402/evm@2.3.1 viem@2.46.0 && ' +
|
|
1104
1060
|
"echo '[moltbank:sandbox] [6/7] verifying mcporter binary...' && " +
|
|
1105
1061
|
"NPM_GLOBAL=$(npm root -g 2>/dev/null | sed 's|/node_modules$|/bin|' || true) && " +
|
|
1106
1062
|
'if [ -n "$NPM_GLOBAL" ] && [ -x "$NPM_GLOBAL/mcporter" ]; then ln -sf "$NPM_GLOBAL/mcporter" /usr/local/bin/mcporter || true; fi && ' +
|
|
@@ -1216,7 +1172,7 @@ async function runSetup(cfg: MoltbankPluginConfig, api: LoggerApi, options: { au
|
|
|
1216
1172
|
return;
|
|
1217
1173
|
}
|
|
1218
1174
|
|
|
1219
|
-
api.logger.info('[moltbank] [sandbox 2/10]
|
|
1175
|
+
api.logger.info('[moltbank] [sandbox 2/10] verifying skill entrypoint...');
|
|
1220
1176
|
ensureSkillFilesUppercase(skillDir, api);
|
|
1221
1177
|
|
|
1222
1178
|
api.logger.info('[moltbank] [sandbox 3/10] applying permissions (chown + chmod)...');
|
|
@@ -1243,7 +1199,7 @@ async function runSetup(cfg: MoltbankPluginConfig, api: LoggerApi, options: { au
|
|
|
1243
1199
|
api.logger.info('[moltbank] [sandbox 5/10] installing skill npm dependencies...');
|
|
1244
1200
|
ensureNpmDeps(skillDir, api, 'sandbox');
|
|
1245
1201
|
|
|
1246
|
-
api.logger.info('[moltbank] [sandbox 6/10]
|
|
1202
|
+
api.logger.info('[moltbank] [sandbox 6/10] validating skill frontmatter...');
|
|
1247
1203
|
fixSkillFrontmatter(skillDir, skillName, api);
|
|
1248
1204
|
|
|
1249
1205
|
api.logger.info('[moltbank] [sandbox 7/10] writing/registering mcporter config...');
|
|
@@ -1273,7 +1229,7 @@ async function runSetup(cfg: MoltbankPluginConfig, api: LoggerApi, options: { au
|
|
|
1273
1229
|
return;
|
|
1274
1230
|
}
|
|
1275
1231
|
|
|
1276
|
-
api.logger.info('[moltbank] [host 3/8]
|
|
1232
|
+
api.logger.info('[moltbank] [host 3/8] verifying skill entrypoint/frontmatter...');
|
|
1277
1233
|
ensureSkillFilesUppercase(skillDir, api);
|
|
1278
1234
|
fixSkillFrontmatter(skillDir, skillName, api);
|
|
1279
1235
|
|
|
@@ -1328,8 +1284,8 @@ async function runSetup(cfg: MoltbankPluginConfig, api: LoggerApi, options: { au
|
|
|
1328
1284
|
} else if (hostReady) {
|
|
1329
1285
|
api.logger.info('[moltbank] ✓ host ready');
|
|
1330
1286
|
}
|
|
1331
|
-
api.logger.info(`[moltbank] skill: ${skillDir}/
|
|
1332
|
-
api.logger.info(`[moltbank] mcporter: ${skillDir}/
|
|
1287
|
+
api.logger.info(`[moltbank] skill: ${skillDir}/skill.md`);
|
|
1288
|
+
api.logger.info(`[moltbank] mcporter: ${skillDir}/assets/mcporter.json`);
|
|
1333
1289
|
if (sandbox) {
|
|
1334
1290
|
const finalConfig = readOpenclawConfig();
|
|
1335
1291
|
const finalEnv = asStringRecord(getNestedValue(finalConfig, ['agents', 'defaults', 'sandbox', 'docker', 'env']));
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "moltbank",
|
|
3
3
|
"name": "MoltBank",
|
|
4
|
-
"description": "MoltBank
|
|
4
|
+
"description": "MoltBank stablecoin treasury plugin for OpenClaw — installs mcporter, npm dependencies, sandbox setup, and the MoltBank skill",
|
|
5
5
|
"configSchema": {
|
|
6
6
|
"type": "object",
|
|
7
7
|
"additionalProperties": false,
|
package/package.json
CHANGED