@moltbankhq/openclaw 0.1.15 → 0.1.17
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 +7 -3
- package/cli.ts +27 -6
- package/index.ts +55 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -44,15 +44,16 @@ After installing, run:
|
|
|
44
44
|
moltbank setup
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
By default, `moltbank setup` issues the browser activation code, starts background finalization, and returns without hanging on approval. Host setup also skips automatic gateway restarts by default so the active chat session is not interrupted. Use `moltbank setup --blocking` or `moltbank setup-blocking` when you want the command to wait for approval and finish readiness verification in the foreground.
|
|
48
48
|
|
|
49
49
|
## CLI Commands
|
|
50
50
|
|
|
51
51
|
| Command | Description |
|
|
52
52
|
|---------|-------------|
|
|
53
|
-
| `moltbank setup` |
|
|
53
|
+
| `moltbank setup` | Start setup in nonblocking mode and return after issuing activation steps |
|
|
54
|
+
| `moltbank setup --blocking` | Run setup and wait for approval in the foreground |
|
|
54
55
|
| `moltbank setup --verbose` | Run setup with detailed logs |
|
|
55
|
-
| `moltbank setup-blocking` |
|
|
56
|
+
| `moltbank setup-blocking` | Run setup and wait for approval |
|
|
56
57
|
| `moltbank status` | Check current auth state |
|
|
57
58
|
| `moltbank auth-status` | Alias for `moltbank status` |
|
|
58
59
|
| `moltbank sandbox-setup` | Reconfigure sandbox Docker settings |
|
|
@@ -65,6 +66,7 @@ CLI flags:
|
|
|
65
66
|
|
|
66
67
|
```bash
|
|
67
68
|
moltbank setup --app-base-url https://app.moltbank.bot --skill-name MoltBank
|
|
69
|
+
moltbank setup --workspace ~/.openclaw/workspace
|
|
68
70
|
```
|
|
69
71
|
|
|
70
72
|
## Environment Variables
|
|
@@ -73,8 +75,10 @@ moltbank setup --app-base-url https://app.moltbank.bot --skill-name MoltBank
|
|
|
73
75
|
|----------|-------------|
|
|
74
76
|
| `APP_BASE_URL` | MoltBank deployment URL (default: `https://app.moltbank.bot`) |
|
|
75
77
|
| `MOLTBANK_SKILL_NAME` | Override skill folder name (default: `MoltBank`) |
|
|
78
|
+
| `OPENCLAW_WORKSPACE` | Override OpenClaw workspace path (default: `~/.openclaw/workspace`) |
|
|
76
79
|
| `MOLTBANK_CREDENTIALS_PATH` | Custom credentials file path |
|
|
77
80
|
| `MOLTBANK_SETUP_AUTH_WAIT_MODE` | `blocking` or `nonblocking` (default: `nonblocking`) |
|
|
81
|
+
| `MOLTBANK_SETUP_RESTART_GATEWAY` | `true` or `false` (default: `false`) |
|
|
78
82
|
|
|
79
83
|
## Capabilities
|
|
80
84
|
|
package/cli.ts
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
createSetupCommandLogger,
|
|
6
6
|
ensureMcporterConfig,
|
|
7
7
|
getAppBaseUrl,
|
|
8
|
+
getSetupAuthWaitMode,
|
|
8
9
|
getSetupGatewayRestartEnabled,
|
|
9
10
|
getSkillDir,
|
|
10
11
|
injectSandboxEnv,
|
|
@@ -16,6 +17,7 @@ import {
|
|
|
16
17
|
type CliConfig = {
|
|
17
18
|
appBaseUrl?: string;
|
|
18
19
|
skillName?: string;
|
|
20
|
+
workspacePath?: string;
|
|
19
21
|
};
|
|
20
22
|
|
|
21
23
|
type ParsedArgs = {
|
|
@@ -35,7 +37,7 @@ Usage:
|
|
|
35
37
|
|
|
36
38
|
Commands:
|
|
37
39
|
setup Run MoltBank setup
|
|
38
|
-
setup-blocking
|
|
40
|
+
setup-blocking Run setup and wait for approval
|
|
39
41
|
status Show current MoltBank auth state
|
|
40
42
|
auth-status Alias for status
|
|
41
43
|
sandbox-setup Reconfigure sandbox Docker settings in openclaw.json
|
|
@@ -45,15 +47,18 @@ Commands:
|
|
|
45
47
|
Options:
|
|
46
48
|
--app-base-url <url> Override MoltBank deployment URL
|
|
47
49
|
--skill-name <name> Override skill folder name
|
|
48
|
-
--
|
|
50
|
+
--workspace <path> Override OpenClaw workspace path
|
|
51
|
+
--blocking Wait for browser approval before setup exits
|
|
49
52
|
--restart-gateway Force gateway restart after successful host setup
|
|
50
|
-
--no-restart-gateway Skip gateway restart after successful host setup
|
|
53
|
+
--no-restart-gateway Skip gateway restart after successful host setup (default)
|
|
51
54
|
--verbose Show detailed setup logs
|
|
52
55
|
-h, --help Show help
|
|
53
56
|
-v, --version Show package version
|
|
54
57
|
|
|
55
58
|
Examples:
|
|
56
59
|
moltbank setup
|
|
60
|
+
moltbank setup --workspace ~/.openclaw/workspace
|
|
61
|
+
moltbank setup --blocking
|
|
57
62
|
moltbank setup --verbose
|
|
58
63
|
moltbank status
|
|
59
64
|
moltbank register --app-base-url https://app.moltbank.bot
|
|
@@ -137,6 +142,21 @@ function parseArgs(argv: string[]): ParsedArgs {
|
|
|
137
142
|
continue;
|
|
138
143
|
}
|
|
139
144
|
|
|
145
|
+
if (arg === '--workspace') {
|
|
146
|
+
const value = argv[index + 1];
|
|
147
|
+
if (!value) {
|
|
148
|
+
throw new Error('missing value for --workspace');
|
|
149
|
+
}
|
|
150
|
+
config.workspacePath = value;
|
|
151
|
+
index += 1;
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (arg.startsWith('--workspace=')) {
|
|
156
|
+
config.workspacePath = arg.slice('--workspace='.length);
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
|
|
140
160
|
if (arg.startsWith('-')) {
|
|
141
161
|
throw new Error(`unknown option: ${arg}`);
|
|
142
162
|
}
|
|
@@ -160,10 +180,11 @@ async function runCommand(parsed: ParsedArgs): Promise<void> {
|
|
|
160
180
|
|
|
161
181
|
switch (parsed.command) {
|
|
162
182
|
case 'setup': {
|
|
163
|
-
const restartGatewayOnSuccess = parsed.restartGateway ?? getSetupGatewayRestartEnabled(
|
|
183
|
+
const restartGatewayOnSuccess = parsed.restartGateway ?? getSetupGatewayRestartEnabled(false);
|
|
164
184
|
const logger = createSetupCommandLogger({ verbose: parsed.verbose, statusCommand: 'moltbank status' });
|
|
185
|
+
const authWaitMode = parsed.blocking ? 'blocking' : getSetupAuthWaitMode('nonblocking');
|
|
165
186
|
try {
|
|
166
|
-
await runSetup(cfg, logger, { authWaitMode
|
|
187
|
+
await runSetup(cfg, logger, { authWaitMode, restartGatewayOnSuccess });
|
|
167
188
|
} finally {
|
|
168
189
|
logger.finish();
|
|
169
190
|
}
|
|
@@ -171,7 +192,7 @@ async function runCommand(parsed: ParsedArgs): Promise<void> {
|
|
|
171
192
|
}
|
|
172
193
|
|
|
173
194
|
case 'setup-blocking': {
|
|
174
|
-
const restartGatewayOnSuccess = parsed.restartGateway ?? getSetupGatewayRestartEnabled(
|
|
195
|
+
const restartGatewayOnSuccess = parsed.restartGateway ?? getSetupGatewayRestartEnabled(false);
|
|
175
196
|
const logger = createSetupCommandLogger({ verbose: parsed.verbose, statusCommand: 'moltbank status' });
|
|
176
197
|
try {
|
|
177
198
|
await runSetup(cfg, logger, { authWaitMode: 'blocking', restartGatewayOnSuccess });
|
package/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
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
|
|
|
@@ -10,6 +10,7 @@ type ParsedJsonObject = Record<string, unknown>;
|
|
|
10
10
|
export interface MoltbankConfig {
|
|
11
11
|
skillName?: string;
|
|
12
12
|
appBaseUrl?: string;
|
|
13
|
+
workspacePath?: string;
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
interface CredentialsOrganization {
|
|
@@ -391,9 +392,13 @@ function resolveWindowsCommandPath(command: string, env: NodeJS.ProcessEnv): str
|
|
|
391
392
|
const extensions = getWindowsCommandExtensions(env);
|
|
392
393
|
|
|
393
394
|
const tryCandidates = (basePath: string): string => {
|
|
394
|
-
if (existsSync(basePath)) return basePath;
|
|
395
|
-
|
|
396
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
|
+
|
|
397
402
|
for (const ext of extensions) {
|
|
398
403
|
if (lower.endsWith(ext)) continue;
|
|
399
404
|
const candidate = `${basePath}${ext}`;
|
|
@@ -402,6 +407,10 @@ function resolveWindowsCommandPath(command: string, env: NodeJS.ProcessEnv): str
|
|
|
402
407
|
}
|
|
403
408
|
}
|
|
404
409
|
|
|
410
|
+
if (existsSync(basePath)) {
|
|
411
|
+
return basePath;
|
|
412
|
+
}
|
|
413
|
+
|
|
405
414
|
return '';
|
|
406
415
|
};
|
|
407
416
|
|
|
@@ -886,8 +895,30 @@ function lastNonEmptyLine(text: string): string {
|
|
|
886
895
|
return lines.length ? lines[lines.length - 1] : '';
|
|
887
896
|
}
|
|
888
897
|
|
|
889
|
-
function
|
|
890
|
-
|
|
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'));
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
function getWorkspaceFromSkillDir(skillDir: string): string {
|
|
920
|
+
const skillsDir = dirname(skillDir);
|
|
921
|
+
return basename(skillsDir) === 'skills' ? dirname(skillsDir) : getWorkspace();
|
|
891
922
|
}
|
|
892
923
|
|
|
893
924
|
export function getSkillName(cfg: MoltbankConfig): string {
|
|
@@ -916,7 +947,7 @@ function isSandboxEnabled(): boolean {
|
|
|
916
947
|
|
|
917
948
|
export function getSkillDir(cfg: MoltbankConfig): string {
|
|
918
949
|
const skillName = getSkillName(cfg);
|
|
919
|
-
return join(getWorkspace(), 'skills', skillName);
|
|
950
|
+
return join(getWorkspace(cfg), 'skills', skillName);
|
|
920
951
|
}
|
|
921
952
|
|
|
922
953
|
function getCredentialsPath(): string {
|
|
@@ -1626,6 +1657,7 @@ function startBackgroundFinalizeAfterAuth(skillDir: string, appBaseUrl: string,
|
|
|
1626
1657
|
env: {
|
|
1627
1658
|
...process.env,
|
|
1628
1659
|
APP_BASE_URL: appBaseUrl,
|
|
1660
|
+
OPENCLAW_WORKSPACE: getWorkspaceFromSkillDir(skillDir),
|
|
1629
1661
|
MOLTBANK_SETUP_AUTH_WAIT_MODE: 'blocking'
|
|
1630
1662
|
},
|
|
1631
1663
|
stdio: 'ignore', // Ignore logs so it doesn't hang the parent
|
|
@@ -2303,7 +2335,11 @@ export async function runSetup(
|
|
|
2303
2335
|
api.logger.info('[moltbank] [host 8/8] running readiness balance check...');
|
|
2304
2336
|
hostReady = runHostReadinessCheck(skillDir, api);
|
|
2305
2337
|
|
|
2306
|
-
|
|
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
|
+
}
|
|
2307
2343
|
|
|
2308
2344
|
if (hostReady && restartGatewayOnSuccess) {
|
|
2309
2345
|
restartGatewayAfterHostSetup(api);
|
|
@@ -2311,13 +2347,19 @@ export async function runSetup(
|
|
|
2311
2347
|
}
|
|
2312
2348
|
|
|
2313
2349
|
api.logger.info(`[moltbank] ══════════════════════════════════════`);
|
|
2314
|
-
|
|
2350
|
+
if (sandbox || hostReady) {
|
|
2351
|
+
api.logger.info(`[moltbank] ✓ setup complete`);
|
|
2352
|
+
} else {
|
|
2353
|
+
api.logger.warn('[moltbank] ✗ setup incomplete');
|
|
2354
|
+
}
|
|
2315
2355
|
if (sandbox) {
|
|
2316
2356
|
api.logger.info('[moltbank] ⏳ sandbox will be recreated in ~8s — send a message to the agent after that');
|
|
2317
2357
|
} else if (hostReady) {
|
|
2318
2358
|
api.logger.info('[moltbank] ✓ host ready');
|
|
2359
|
+
} else {
|
|
2360
|
+
api.logger.warn('[moltbank] ✗ host not ready');
|
|
2319
2361
|
}
|
|
2320
|
-
api.logger.info(`[moltbank] skill: ${skillDir}/SKILL.md`);
|
|
2362
|
+
api.logger.info(`[moltbank] skill: ${skillDir}/skill/SKILL.md`);
|
|
2321
2363
|
api.logger.info(`[moltbank] mcporter: ${skillDir}/assets/mcporter.json`);
|
|
2322
2364
|
if (sandbox) {
|
|
2323
2365
|
const finalConfig = readOpenclawConfig();
|
|
@@ -2359,5 +2401,9 @@ export async function runSetup(
|
|
|
2359
2401
|
}
|
|
2360
2402
|
}
|
|
2361
2403
|
api.logger.info(`[moltbank] ══════════════════════════════════════`);
|
|
2404
|
+
|
|
2405
|
+
if (!sandbox && !hostReady) {
|
|
2406
|
+
throw new Error('host setup incomplete: authenticated readiness verification failed');
|
|
2407
|
+
}
|
|
2362
2408
|
}
|
|
2363
2409
|
|
package/package.json
CHANGED