@moltbankhq/openclaw 0.1.14 → 0.1.16
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 +4 -27
- package/cli.ts +18 -0
- package/index.ts +67 -208
- package/package.json +3 -9
- package/openclaw.plugin.json +0 -29
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @moltbankhq/openclaw
|
|
2
2
|
|
|
3
|
-
Standalone CLI
|
|
3
|
+
Standalone CLI for [MoltBank](https://moltbank.bot) — stablecoin treasury controls, approvals, and audit trails for agent fleets.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -22,12 +22,6 @@ Or from a local install:
|
|
|
22
22
|
npm exec --package @moltbankhq/openclaw -- moltbank setup
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
OpenClaw plugin mode still exists in this pass for compatibility:
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
openclaw plugins install @moltbankhq/openclaw
|
|
29
|
-
```
|
|
30
|
-
|
|
31
25
|
## What it does
|
|
32
26
|
|
|
33
27
|
This package connects your OpenClaw agent to MoltBank's stablecoin treasury infrastructure. During setup, it:
|
|
@@ -40,7 +34,7 @@ This package connects your OpenClaw agent to MoltBank's stablecoin treasury infr
|
|
|
40
34
|
|
|
41
35
|
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.
|
|
42
36
|
|
|
43
|
-
The standalone `moltbank` CLI is for install, setup, auth status, and repair flows. Actual treasury operations should run through the installed skill wrapper scripts inside the skill directory.
|
|
37
|
+
The standalone `moltbank` CLI is the supported path for install, setup, auth status, and repair flows. Actual treasury operations should run through the installed skill wrapper scripts inside the skill directory.
|
|
44
38
|
|
|
45
39
|
## Setup
|
|
46
40
|
|
|
@@ -71,25 +65,7 @@ CLI flags:
|
|
|
71
65
|
|
|
72
66
|
```bash
|
|
73
67
|
moltbank setup --app-base-url https://app.moltbank.bot --skill-name MoltBank
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
Plugin mode can still read optional config from your `openclaw.json`:
|
|
77
|
-
|
|
78
|
-
Optional config in your `openclaw.json`:
|
|
79
|
-
|
|
80
|
-
```json
|
|
81
|
-
{
|
|
82
|
-
"plugins": {
|
|
83
|
-
"entries": {
|
|
84
|
-
"moltbank": {
|
|
85
|
-
"config": {
|
|
86
|
-
"appBaseUrl": "https://app.moltbank.bot",
|
|
87
|
-
"skillName": "MoltBank"
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
68
|
+
moltbank setup --workspace ~/.openclaw/workspace
|
|
93
69
|
```
|
|
94
70
|
|
|
95
71
|
## Environment Variables
|
|
@@ -98,6 +74,7 @@ Optional config in your `openclaw.json`:
|
|
|
98
74
|
|----------|-------------|
|
|
99
75
|
| `APP_BASE_URL` | MoltBank deployment URL (default: `https://app.moltbank.bot`) |
|
|
100
76
|
| `MOLTBANK_SKILL_NAME` | Override skill folder name (default: `MoltBank`) |
|
|
77
|
+
| `OPENCLAW_WORKSPACE` | Override OpenClaw workspace path (default: `~/.openclaw/workspace`) |
|
|
101
78
|
| `MOLTBANK_CREDENTIALS_PATH` | Custom credentials file path |
|
|
102
79
|
| `MOLTBANK_SETUP_AUTH_WAIT_MODE` | `blocking` or `nonblocking` (default: `nonblocking`) |
|
|
103
80
|
|
package/cli.ts
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
type CliConfig = {
|
|
17
17
|
appBaseUrl?: string;
|
|
18
18
|
skillName?: string;
|
|
19
|
+
workspacePath?: string;
|
|
19
20
|
};
|
|
20
21
|
|
|
21
22
|
type ParsedArgs = {
|
|
@@ -45,6 +46,7 @@ Commands:
|
|
|
45
46
|
Options:
|
|
46
47
|
--app-base-url <url> Override MoltBank deployment URL
|
|
47
48
|
--skill-name <name> Override skill folder name
|
|
49
|
+
--workspace <path> Override OpenClaw workspace path
|
|
48
50
|
--blocking Compatibility flag; setup already waits for approval
|
|
49
51
|
--restart-gateway Force gateway restart after successful host setup
|
|
50
52
|
--no-restart-gateway Skip gateway restart after successful host setup
|
|
@@ -54,6 +56,7 @@ Options:
|
|
|
54
56
|
|
|
55
57
|
Examples:
|
|
56
58
|
moltbank setup
|
|
59
|
+
moltbank setup --workspace ~/.openclaw/workspace
|
|
57
60
|
moltbank setup --verbose
|
|
58
61
|
moltbank status
|
|
59
62
|
moltbank register --app-base-url https://app.moltbank.bot
|
|
@@ -137,6 +140,21 @@ function parseArgs(argv: string[]): ParsedArgs {
|
|
|
137
140
|
continue;
|
|
138
141
|
}
|
|
139
142
|
|
|
143
|
+
if (arg === '--workspace') {
|
|
144
|
+
const value = argv[index + 1];
|
|
145
|
+
if (!value) {
|
|
146
|
+
throw new Error('missing value for --workspace');
|
|
147
|
+
}
|
|
148
|
+
config.workspacePath = value;
|
|
149
|
+
index += 1;
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (arg.startsWith('--workspace=')) {
|
|
154
|
+
config.workspacePath = arg.slice('--workspace='.length);
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
|
|
140
158
|
if (arg.startsWith('-')) {
|
|
141
159
|
throw new Error(`unknown option: ${arg}`);
|
|
142
160
|
}
|
package/index.ts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { spawn, spawnSync } from 'child_process';
|
|
2
2
|
import { chmodSync, chownSync, existsSync, mkdirSync, readdirSync, readFileSync, unlinkSync, writeFileSync, type Dirent } from 'fs';
|
|
3
|
-
import { join, dirname, basename } from 'path';
|
|
3
|
+
import { join, dirname, basename, resolve } from 'path';
|
|
4
4
|
import { homedir, userInfo } from 'os';
|
|
5
5
|
const IS_WIN = process.platform === 'win32';
|
|
6
6
|
|
|
7
7
|
type OpenclawConfig = Record<string, unknown>;
|
|
8
8
|
type ParsedJsonObject = Record<string, unknown>;
|
|
9
9
|
|
|
10
|
-
export interface
|
|
10
|
+
export interface MoltbankConfig {
|
|
11
11
|
skillName?: string;
|
|
12
12
|
appBaseUrl?: string;
|
|
13
|
+
workspacePath?: string;
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
interface CredentialsOrganization {
|
|
@@ -53,36 +54,6 @@ export interface SetupCommandLoggerOptions {
|
|
|
53
54
|
statusCommand?: string;
|
|
54
55
|
}
|
|
55
56
|
|
|
56
|
-
interface ServiceDefinition {
|
|
57
|
-
id: string;
|
|
58
|
-
start: () => void | Promise<void>;
|
|
59
|
-
stop: () => void | Promise<void>;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
interface CliCommandLike {
|
|
63
|
-
command(name: string): CliCommandLike;
|
|
64
|
-
createCommand(name: string): CliCommandLike;
|
|
65
|
-
description(text: string): CliCommandLike;
|
|
66
|
-
addCommand(command: CliCommandLike): CliCommandLike;
|
|
67
|
-
action(handler: () => void | Promise<void>): CliCommandLike;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
interface PluginApiConfig {
|
|
71
|
-
plugins?: {
|
|
72
|
-
entries?: {
|
|
73
|
-
moltbank?: {
|
|
74
|
-
config?: MoltbankPluginConfig;
|
|
75
|
-
};
|
|
76
|
-
};
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
interface PluginApi extends LoggerApi {
|
|
81
|
-
config?: PluginApiConfig;
|
|
82
|
-
registerService(service: ServiceDefinition): void;
|
|
83
|
-
registerCli(handler: (args: { program: CliCommandLike }) => void, options: { commands: string[] }): void;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
57
|
export type AuthWaitMode = 'blocking' | 'nonblocking';
|
|
87
58
|
const oauthPollers = new Map<string, ReturnType<typeof spawn>>();
|
|
88
59
|
const backgroundFinalizers = new Map<string, ReturnType<typeof spawn>>();
|
|
@@ -421,9 +392,13 @@ function resolveWindowsCommandPath(command: string, env: NodeJS.ProcessEnv): str
|
|
|
421
392
|
const extensions = getWindowsCommandExtensions(env);
|
|
422
393
|
|
|
423
394
|
const tryCandidates = (basePath: string): string => {
|
|
424
|
-
if (existsSync(basePath)) return basePath;
|
|
425
|
-
|
|
426
395
|
const lower = basePath.toLowerCase();
|
|
396
|
+
const hasKnownExtension = extensions.some((ext) => lower.endsWith(ext));
|
|
397
|
+
|
|
398
|
+
if (hasKnownExtension && existsSync(basePath)) {
|
|
399
|
+
return basePath;
|
|
400
|
+
}
|
|
401
|
+
|
|
427
402
|
for (const ext of extensions) {
|
|
428
403
|
if (lower.endsWith(ext)) continue;
|
|
429
404
|
const candidate = `${basePath}${ext}`;
|
|
@@ -432,6 +407,10 @@ function resolveWindowsCommandPath(command: string, env: NodeJS.ProcessEnv): str
|
|
|
432
407
|
}
|
|
433
408
|
}
|
|
434
409
|
|
|
410
|
+
if (existsSync(basePath)) {
|
|
411
|
+
return basePath;
|
|
412
|
+
}
|
|
413
|
+
|
|
435
414
|
return '';
|
|
436
415
|
};
|
|
437
416
|
|
|
@@ -916,19 +895,41 @@ function lastNonEmptyLine(text: string): string {
|
|
|
916
895
|
return lines.length ? lines[lines.length - 1] : '';
|
|
917
896
|
}
|
|
918
897
|
|
|
919
|
-
function
|
|
920
|
-
|
|
898
|
+
function normalizeWorkspacePath(rawPath: string): string {
|
|
899
|
+
const trimmed = rawPath.trim();
|
|
900
|
+
if (!trimmed) {
|
|
901
|
+
return join(homedir(), '.openclaw', 'workspace');
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
if (trimmed === '~') {
|
|
905
|
+
return homedir();
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
if (trimmed.startsWith('~/') || trimmed.startsWith('~\\')) {
|
|
909
|
+
return resolve(join(homedir(), trimmed.slice(2)));
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
return resolve(trimmed);
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
export function getWorkspace(cfg?: MoltbankConfig): string {
|
|
916
|
+
return normalizeWorkspacePath(cfg?.workspacePath || process.env.OPENCLAW_WORKSPACE || join(homedir(), '.openclaw', 'workspace'));
|
|
921
917
|
}
|
|
922
918
|
|
|
923
|
-
|
|
919
|
+
function getWorkspaceFromSkillDir(skillDir: string): string {
|
|
920
|
+
const skillsDir = dirname(skillDir);
|
|
921
|
+
return basename(skillsDir) === 'skills' ? dirname(skillsDir) : getWorkspace();
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
export function getSkillName(cfg: MoltbankConfig): string {
|
|
924
925
|
return cfg?.skillName || process.env.MOLTBANK_SKILL_NAME || 'MoltBank';
|
|
925
926
|
}
|
|
926
927
|
|
|
927
|
-
export function getAppBaseUrl(cfg:
|
|
928
|
+
export function getAppBaseUrl(cfg: MoltbankConfig): string {
|
|
928
929
|
return (cfg?.appBaseUrl || process.env.APP_BASE_URL || 'https://app.moltbank.bot').trim();
|
|
929
930
|
}
|
|
930
931
|
|
|
931
|
-
export function getSkillBundleBaseUrl(cfg:
|
|
932
|
+
export function getSkillBundleBaseUrl(cfg: MoltbankConfig): string {
|
|
932
933
|
const base = getAppBaseUrl(cfg).replace(/\/$/, '');
|
|
933
934
|
return base.endsWith('/skill') ? base : `${base}/skill`;
|
|
934
935
|
}
|
|
@@ -944,9 +945,9 @@ function isSandboxEnabled(): boolean {
|
|
|
944
945
|
}
|
|
945
946
|
}
|
|
946
947
|
|
|
947
|
-
export function getSkillDir(cfg:
|
|
948
|
+
export function getSkillDir(cfg: MoltbankConfig): string {
|
|
948
949
|
const skillName = getSkillName(cfg);
|
|
949
|
-
return join(getWorkspace(), 'skills', skillName);
|
|
950
|
+
return join(getWorkspace(cfg), 'skills', skillName);
|
|
950
951
|
}
|
|
951
952
|
|
|
952
953
|
function getCredentialsPath(): string {
|
|
@@ -1065,47 +1066,6 @@ function setNestedValue(obj: Record<string, unknown>, path: string[], value: unk
|
|
|
1065
1066
|
current[path[path.length - 1]] = value;
|
|
1066
1067
|
}
|
|
1067
1068
|
|
|
1068
|
-
function cleanupStaleMoltbankPluginLoadPaths(api: LoggerApi): boolean {
|
|
1069
|
-
try {
|
|
1070
|
-
const config = readOpenclawConfig();
|
|
1071
|
-
const loadPathsPath = ['plugins', 'load', 'paths'];
|
|
1072
|
-
const current = getNestedValue(config, loadPathsPath);
|
|
1073
|
-
if (!Array.isArray(current)) return false;
|
|
1074
|
-
|
|
1075
|
-
const removed: string[] = [];
|
|
1076
|
-
const next: unknown[] = [];
|
|
1077
|
-
|
|
1078
|
-
for (const entry of current) {
|
|
1079
|
-
if (typeof entry !== 'string') {
|
|
1080
|
-
next.push(entry);
|
|
1081
|
-
continue;
|
|
1082
|
-
}
|
|
1083
|
-
|
|
1084
|
-
const normalized = entry.replace(/\\/g, '/').toLowerCase();
|
|
1085
|
-
const looksLikeMoltbankPath = normalized.includes('moltbank');
|
|
1086
|
-
if (looksLikeMoltbankPath && !existsSync(entry)) {
|
|
1087
|
-
removed.push(entry);
|
|
1088
|
-
continue;
|
|
1089
|
-
}
|
|
1090
|
-
|
|
1091
|
-
next.push(entry);
|
|
1092
|
-
}
|
|
1093
|
-
|
|
1094
|
-
if (removed.length === 0) {
|
|
1095
|
-
api.logger.info('[moltbank] ✓ no stale MoltBank plugin load paths found');
|
|
1096
|
-
return false;
|
|
1097
|
-
}
|
|
1098
|
-
|
|
1099
|
-
setNestedValue(config, loadPathsPath, next);
|
|
1100
|
-
writeOpenclawConfig(config);
|
|
1101
|
-
api.logger.info(`[moltbank] ✓ removed stale MoltBank plugin load path(s): ${removed.join(', ')}`);
|
|
1102
|
-
return true;
|
|
1103
|
-
} catch (e) {
|
|
1104
|
-
api.logger.warn('[moltbank] could not clean stale MoltBank plugin load paths: ' + String(e));
|
|
1105
|
-
return false;
|
|
1106
|
-
}
|
|
1107
|
-
}
|
|
1108
|
-
|
|
1109
1069
|
// ─── mcporter ────────────────────────────────────────────────────────────────
|
|
1110
1070
|
|
|
1111
1071
|
function ensureMcporter(api: LoggerApi) {
|
|
@@ -1692,11 +1652,12 @@ function startBackgroundFinalizeAfterAuth(skillDir: string, appBaseUrl: string,
|
|
|
1692
1652
|
}
|
|
1693
1653
|
if (existing) backgroundFinalizers.delete(skillDir);
|
|
1694
1654
|
|
|
1695
|
-
const child = spawn('
|
|
1655
|
+
const child = spawn('moltbank', ['setup-blocking'], {
|
|
1696
1656
|
cwd: skillDir,
|
|
1697
1657
|
env: {
|
|
1698
1658
|
...process.env,
|
|
1699
1659
|
APP_BASE_URL: appBaseUrl,
|
|
1660
|
+
OPENCLAW_WORKSPACE: getWorkspaceFromSkillDir(skillDir),
|
|
1700
1661
|
MOLTBANK_SETUP_AUTH_WAIT_MODE: 'blocking'
|
|
1701
1662
|
},
|
|
1702
1663
|
stdio: 'ignore', // Ignore logs so it doesn't hang the parent
|
|
@@ -1849,7 +1810,7 @@ function ensureMoltbankAuth(skillDir: string, appBaseUrl: string, api: LoggerApi
|
|
|
1849
1810
|
const backgroundTimeoutSeconds = Math.max(30, expiresAt - now - 5);
|
|
1850
1811
|
startBackgroundOauthPoll(skillDir, appBaseUrl, credsPath, deviceCode, backgroundTimeoutSeconds, api);
|
|
1851
1812
|
api.logger.info('[moltbank] once approved in browser, setup finalization will continue automatically');
|
|
1852
|
-
api.logger.info('[moltbank] optional immediate check: `
|
|
1813
|
+
api.logger.info('[moltbank] optional immediate check: `moltbank status`');
|
|
1853
1814
|
return false;
|
|
1854
1815
|
}
|
|
1855
1816
|
|
|
@@ -2249,7 +2210,7 @@ function restartGatewayAfterHostSetup(api: LoggerApi): boolean {
|
|
|
2249
2210
|
// ─── main setup ───────────────────────────────────────────────────────────────
|
|
2250
2211
|
|
|
2251
2212
|
export async function runSetup(
|
|
2252
|
-
cfg:
|
|
2213
|
+
cfg: MoltbankConfig,
|
|
2253
2214
|
api: LoggerApi,
|
|
2254
2215
|
options: { authWaitMode?: AuthWaitMode; restartGatewayOnSuccess?: boolean } = {}
|
|
2255
2216
|
) {
|
|
@@ -2268,9 +2229,6 @@ export async function runSetup(
|
|
|
2268
2229
|
api.logger.info(`[moltbank] skill dir: ${skillDir}`);
|
|
2269
2230
|
api.logger.info(`[moltbank] base url: ${appBaseUrl}`);
|
|
2270
2231
|
api.logger.info(`[moltbank] ══════════════════════════════════════`);
|
|
2271
|
-
api.logger.info('[moltbank] preflight: cleaning stale MoltBank plugin load paths...');
|
|
2272
|
-
cleanupStaleMoltbankPluginLoadPaths(api);
|
|
2273
|
-
|
|
2274
2232
|
if (sandbox) {
|
|
2275
2233
|
api.logger.info('[moltbank] configuring sandbox mode...');
|
|
2276
2234
|
|
|
@@ -2298,10 +2256,10 @@ export async function runSetup(
|
|
|
2298
2256
|
if (pending) {
|
|
2299
2257
|
api.logger.warn('[moltbank] sandbox auth pending — startup continues without blocking channel startup');
|
|
2300
2258
|
api.logger.info('[moltbank] setup will finalize automatically after browser approval');
|
|
2301
|
-
api.logger.info('[moltbank] optional immediate check: `
|
|
2259
|
+
api.logger.info('[moltbank] optional immediate check: `moltbank status`');
|
|
2302
2260
|
} else {
|
|
2303
2261
|
api.logger.warn('[moltbank] sandbox auth setup failed before issuing a valid device code');
|
|
2304
|
-
api.logger.warn('[moltbank] review the previous error and rerun `
|
|
2262
|
+
api.logger.warn('[moltbank] review the previous error and rerun `moltbank setup`');
|
|
2305
2263
|
}
|
|
2306
2264
|
return;
|
|
2307
2265
|
}
|
|
@@ -2357,10 +2315,10 @@ export async function runSetup(
|
|
|
2357
2315
|
if (pending) {
|
|
2358
2316
|
api.logger.warn('[moltbank] host auth pending — startup continues without blocking channel startup');
|
|
2359
2317
|
api.logger.info('[moltbank] setup will finalize automatically after browser approval');
|
|
2360
|
-
api.logger.info('[moltbank] optional immediate check: `
|
|
2318
|
+
api.logger.info('[moltbank] optional immediate check: `moltbank status`');
|
|
2361
2319
|
} else {
|
|
2362
2320
|
api.logger.warn('[moltbank] host auth setup failed before issuing a valid device code');
|
|
2363
|
-
api.logger.warn('[moltbank] review the previous error and rerun `
|
|
2321
|
+
api.logger.warn('[moltbank] review the previous error and rerun `moltbank setup`');
|
|
2364
2322
|
}
|
|
2365
2323
|
return;
|
|
2366
2324
|
}
|
|
@@ -2377,7 +2335,11 @@ export async function runSetup(
|
|
|
2377
2335
|
api.logger.info('[moltbank] [host 8/8] running readiness balance check...');
|
|
2378
2336
|
hostReady = runHostReadinessCheck(skillDir, api);
|
|
2379
2337
|
|
|
2380
|
-
|
|
2338
|
+
if (hostReady) {
|
|
2339
|
+
api.logger.info('[moltbank] host mode — setup completed with onboarding flow');
|
|
2340
|
+
} else {
|
|
2341
|
+
api.logger.warn('[moltbank] host mode setup finished, but operational readiness verification failed');
|
|
2342
|
+
}
|
|
2381
2343
|
|
|
2382
2344
|
if (hostReady && restartGatewayOnSuccess) {
|
|
2383
2345
|
restartGatewayAfterHostSetup(api);
|
|
@@ -2385,13 +2347,19 @@ export async function runSetup(
|
|
|
2385
2347
|
}
|
|
2386
2348
|
|
|
2387
2349
|
api.logger.info(`[moltbank] ══════════════════════════════════════`);
|
|
2388
|
-
|
|
2350
|
+
if (sandbox || hostReady) {
|
|
2351
|
+
api.logger.info(`[moltbank] ✓ setup complete`);
|
|
2352
|
+
} else {
|
|
2353
|
+
api.logger.warn('[moltbank] ✗ setup incomplete');
|
|
2354
|
+
}
|
|
2389
2355
|
if (sandbox) {
|
|
2390
2356
|
api.logger.info('[moltbank] ⏳ sandbox will be recreated in ~8s — send a message to the agent after that');
|
|
2391
2357
|
} else if (hostReady) {
|
|
2392
2358
|
api.logger.info('[moltbank] ✓ host ready');
|
|
2359
|
+
} else {
|
|
2360
|
+
api.logger.warn('[moltbank] ✗ host not ready');
|
|
2393
2361
|
}
|
|
2394
|
-
api.logger.info(`[moltbank] skill: ${skillDir}/SKILL.md`);
|
|
2362
|
+
api.logger.info(`[moltbank] skill: ${skillDir}/skill/SKILL.md`);
|
|
2395
2363
|
api.logger.info(`[moltbank] mcporter: ${skillDir}/assets/mcporter.json`);
|
|
2396
2364
|
if (sandbox) {
|
|
2397
2365
|
const finalConfig = readOpenclawConfig();
|
|
@@ -2433,118 +2401,9 @@ export async function runSetup(
|
|
|
2433
2401
|
}
|
|
2434
2402
|
}
|
|
2435
2403
|
api.logger.info(`[moltbank] ══════════════════════════════════════`);
|
|
2436
|
-
}
|
|
2437
|
-
|
|
2438
|
-
// ─── plugin register ──────────────────────────────────────────────────────────
|
|
2439
|
-
|
|
2440
|
-
export default function register(api: PluginApi) {
|
|
2441
|
-
const cfg: MoltbankPluginConfig = api.config?.plugins?.entries?.moltbank?.config ?? {};
|
|
2442
2404
|
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
await runSetup(cfg, api, { authWaitMode: 'nonblocking' });
|
|
2447
|
-
},
|
|
2448
|
-
stop: async () => {
|
|
2449
|
-
stopBackgroundOauthPoll(getSkillDir(cfg));
|
|
2450
|
-
stopBackgroundFinalize(getSkillDir(cfg));
|
|
2451
|
-
api.logger.info('[moltbank] plugin stopped');
|
|
2452
|
-
}
|
|
2453
|
-
});
|
|
2454
|
-
|
|
2455
|
-
api.registerCli(
|
|
2456
|
-
({ program }: { program: CliCommandLike }) => {
|
|
2457
|
-
program
|
|
2458
|
-
.command('moltbank')
|
|
2459
|
-
.description('MoltBank plugin commands')
|
|
2460
|
-
.addCommand(
|
|
2461
|
-
program
|
|
2462
|
-
.createCommand('setup')
|
|
2463
|
-
.description('Re-run MoltBank setup')
|
|
2464
|
-
.action(async () => {
|
|
2465
|
-
const verbose = process.argv.includes('--verbose');
|
|
2466
|
-
const restartGatewayOnSuccess = getSetupGatewayRestartEnabled(IS_WIN);
|
|
2467
|
-
const logger = createSetupCommandLogger({ verbose, statusCommand: 'openclaw moltbank status' });
|
|
2468
|
-
try {
|
|
2469
|
-
await runSetup(cfg, logger, { authWaitMode: 'blocking', restartGatewayOnSuccess });
|
|
2470
|
-
} finally {
|
|
2471
|
-
logger.finish();
|
|
2472
|
-
}
|
|
2473
|
-
})
|
|
2474
|
-
)
|
|
2475
|
-
.addCommand(
|
|
2476
|
-
program
|
|
2477
|
-
.createCommand('setup-blocking')
|
|
2478
|
-
.description('Re-run full MoltBank setup and wait for OAuth approval')
|
|
2479
|
-
.action(async () => {
|
|
2480
|
-
const verbose = process.argv.includes('--verbose');
|
|
2481
|
-
const restartGatewayOnSuccess = getSetupGatewayRestartEnabled(IS_WIN);
|
|
2482
|
-
const logger = createSetupCommandLogger({ verbose, statusCommand: 'openclaw moltbank status' });
|
|
2483
|
-
try {
|
|
2484
|
-
await runSetup(cfg, logger, { authWaitMode: 'blocking', restartGatewayOnSuccess });
|
|
2485
|
-
} finally {
|
|
2486
|
-
logger.finish();
|
|
2487
|
-
}
|
|
2488
|
-
})
|
|
2489
|
-
)
|
|
2490
|
-
.addCommand(
|
|
2491
|
-
program
|
|
2492
|
-
.createCommand('sandbox-setup')
|
|
2493
|
-
.description('Reconfigure sandbox docker in openclaw.json')
|
|
2494
|
-
.action(() => {
|
|
2495
|
-
const changed = configureSandbox({ logger: console });
|
|
2496
|
-
if (changed) {
|
|
2497
|
-
recreateSandboxAndRestart({ logger: console });
|
|
2498
|
-
} else {
|
|
2499
|
-
console.log('[moltbank] No sandbox docker changes — not scheduling teardown');
|
|
2500
|
-
}
|
|
2501
|
-
})
|
|
2502
|
-
)
|
|
2503
|
-
.addCommand(
|
|
2504
|
-
program
|
|
2505
|
-
.createCommand('inject-key')
|
|
2506
|
-
.description('Re-inject sandbox env vars from credentials.json')
|
|
2507
|
-
.action(() => {
|
|
2508
|
-
const skillDir = getSkillDir(cfg);
|
|
2509
|
-
const changed = injectSandboxEnv(skillDir, { logger: console });
|
|
2510
|
-
if (changed) {
|
|
2511
|
-
recreateSandboxAndRestart({ logger: console });
|
|
2512
|
-
} else {
|
|
2513
|
-
console.log('[moltbank] No env changes — not scheduling teardown');
|
|
2514
|
-
}
|
|
2515
|
-
})
|
|
2516
|
-
)
|
|
2517
|
-
.addCommand(
|
|
2518
|
-
program
|
|
2519
|
-
.createCommand('status')
|
|
2520
|
-
.description('Show current MoltBank auth state')
|
|
2521
|
-
.action(() => {
|
|
2522
|
-
const appBaseUrl = getAppBaseUrl(cfg);
|
|
2523
|
-
const skillDir = getSkillDir(cfg);
|
|
2524
|
-
printAuthStatus(skillDir, appBaseUrl, { logger: console });
|
|
2525
|
-
})
|
|
2526
|
-
)
|
|
2527
|
-
.addCommand(
|
|
2528
|
-
program
|
|
2529
|
-
.createCommand('auth-status')
|
|
2530
|
-
.description('Show current MoltBank auth state (credentials, pending code, background poll)')
|
|
2531
|
-
.action(() => {
|
|
2532
|
-
const appBaseUrl = getAppBaseUrl(cfg);
|
|
2533
|
-
const skillDir = getSkillDir(cfg);
|
|
2534
|
-
printAuthStatus(skillDir, appBaseUrl, { logger: console });
|
|
2535
|
-
})
|
|
2536
|
-
)
|
|
2537
|
-
.addCommand(
|
|
2538
|
-
program
|
|
2539
|
-
.createCommand('register')
|
|
2540
|
-
.description('Re-register mcporter server')
|
|
2541
|
-
.action(() => {
|
|
2542
|
-
const appBaseUrl = getAppBaseUrl(cfg);
|
|
2543
|
-
const skillDir = getSkillDir(cfg);
|
|
2544
|
-
ensureMcporterConfig(skillDir, appBaseUrl, { logger: console });
|
|
2545
|
-
})
|
|
2546
|
-
);
|
|
2547
|
-
},
|
|
2548
|
-
{ commands: ['moltbank'] }
|
|
2549
|
-
);
|
|
2405
|
+
if (!sandbox && !hostReady) {
|
|
2406
|
+
throw new Error('host setup incomplete: authenticated readiness verification failed');
|
|
2407
|
+
}
|
|
2550
2408
|
}
|
|
2409
|
+
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moltbankhq/openclaw",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "MoltBank stablecoin treasury CLI and OpenClaw
|
|
3
|
+
"version": "0.1.16",
|
|
4
|
+
"description": "MoltBank stablecoin treasury CLI and OpenClaw skill installer",
|
|
5
5
|
"homepage": "https://github.com/moltbankhq/openclaw-plugin#readme",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -24,14 +24,8 @@
|
|
|
24
24
|
"README.md",
|
|
25
25
|
"bin/",
|
|
26
26
|
"cli.ts",
|
|
27
|
-
"index.ts"
|
|
28
|
-
"openclaw.plugin.json"
|
|
27
|
+
"index.ts"
|
|
29
28
|
],
|
|
30
|
-
"openclaw": {
|
|
31
|
-
"extensions": [
|
|
32
|
-
"./index.ts"
|
|
33
|
-
]
|
|
34
|
-
},
|
|
35
29
|
"keywords": [
|
|
36
30
|
"moltbank",
|
|
37
31
|
"openclaw",
|
package/openclaw.plugin.json
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "moltbank",
|
|
3
|
-
"name": "MoltBank",
|
|
4
|
-
"description": "MoltBank stablecoin treasury plugin for OpenClaw — installs mcporter, npm dependencies, sandbox setup, and the MoltBank skill",
|
|
5
|
-
"configSchema": {
|
|
6
|
-
"type": "object",
|
|
7
|
-
"additionalProperties": false,
|
|
8
|
-
"properties": {
|
|
9
|
-
"appBaseUrl": {
|
|
10
|
-
"type": "string",
|
|
11
|
-
"description": "MoltBank deployment URL"
|
|
12
|
-
},
|
|
13
|
-
"skillName": {
|
|
14
|
-
"type": "string",
|
|
15
|
-
"description": "Override skill folder name (default: MoltBank)"
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
},
|
|
19
|
-
"uiHints": {
|
|
20
|
-
"appBaseUrl": {
|
|
21
|
-
"label": "App Base URL",
|
|
22
|
-
"placeholder": "https://app.moltbank.bot"
|
|
23
|
-
},
|
|
24
|
-
"skillName": {
|
|
25
|
-
"label": "Skill Name",
|
|
26
|
-
"placeholder": "MoltBank"
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|