@moltbankhq/openclaw 0.1.5 → 0.1.7
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/cli.ts +35 -12
- package/index.ts +240 -16
- package/package.json +1 -1
package/cli.ts
CHANGED
|
@@ -2,9 +2,9 @@ import { readFileSync } from 'fs';
|
|
|
2
2
|
import process from 'process';
|
|
3
3
|
import {
|
|
4
4
|
configureSandbox,
|
|
5
|
+
createSetupCommandLogger,
|
|
5
6
|
ensureMcporterConfig,
|
|
6
7
|
getAppBaseUrl,
|
|
7
|
-
getSetupAuthWaitMode,
|
|
8
8
|
getSkillDir,
|
|
9
9
|
injectSandboxEnv,
|
|
10
10
|
printAuthStatus,
|
|
@@ -23,6 +23,7 @@ type ParsedArgs = {
|
|
|
23
23
|
help: boolean;
|
|
24
24
|
version: boolean;
|
|
25
25
|
blocking: boolean;
|
|
26
|
+
verbose: boolean;
|
|
26
27
|
};
|
|
27
28
|
|
|
28
29
|
const HELP_TEXT = `MoltBank CLI
|
|
@@ -31,9 +32,10 @@ Usage:
|
|
|
31
32
|
moltbank <command> [options]
|
|
32
33
|
|
|
33
34
|
Commands:
|
|
34
|
-
setup Run MoltBank setup
|
|
35
|
-
setup-blocking
|
|
36
|
-
|
|
35
|
+
setup Run MoltBank setup
|
|
36
|
+
setup-blocking Alias for setup
|
|
37
|
+
status Show current MoltBank auth state
|
|
38
|
+
auth-status Alias for status
|
|
37
39
|
sandbox-setup Reconfigure sandbox Docker settings in openclaw.json
|
|
38
40
|
inject-key Re-inject sandbox env vars from credentials.json
|
|
39
41
|
register Re-register mcporter MCP config
|
|
@@ -41,14 +43,15 @@ Commands:
|
|
|
41
43
|
Options:
|
|
42
44
|
--app-base-url <url> Override MoltBank deployment URL
|
|
43
45
|
--skill-name <name> Override skill folder name
|
|
44
|
-
--blocking
|
|
46
|
+
--blocking Compatibility flag; setup already waits for approval
|
|
47
|
+
--verbose Show detailed setup logs
|
|
45
48
|
-h, --help Show help
|
|
46
49
|
-v, --version Show package version
|
|
47
50
|
|
|
48
51
|
Examples:
|
|
49
52
|
moltbank setup
|
|
50
|
-
moltbank setup --
|
|
51
|
-
moltbank
|
|
53
|
+
moltbank setup --verbose
|
|
54
|
+
moltbank status
|
|
52
55
|
moltbank register --app-base-url https://app.moltbank.bot
|
|
53
56
|
`;
|
|
54
57
|
|
|
@@ -64,6 +67,7 @@ function parseArgs(argv: string[]): ParsedArgs {
|
|
|
64
67
|
let help = false;
|
|
65
68
|
let version = false;
|
|
66
69
|
let blocking = false;
|
|
70
|
+
let verbose = false;
|
|
67
71
|
|
|
68
72
|
for (let index = 0; index < argv.length; index += 1) {
|
|
69
73
|
const arg = argv[index];
|
|
@@ -83,6 +87,11 @@ function parseArgs(argv: string[]): ParsedArgs {
|
|
|
83
87
|
continue;
|
|
84
88
|
}
|
|
85
89
|
|
|
90
|
+
if (arg === '--verbose') {
|
|
91
|
+
verbose = true;
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
|
|
86
95
|
if (arg === '--app-base-url') {
|
|
87
96
|
const value = argv[index + 1];
|
|
88
97
|
if (!value) {
|
|
@@ -125,32 +134,44 @@ function parseArgs(argv: string[]): ParsedArgs {
|
|
|
125
134
|
config,
|
|
126
135
|
help,
|
|
127
136
|
version,
|
|
128
|
-
blocking
|
|
137
|
+
blocking,
|
|
138
|
+
verbose
|
|
129
139
|
};
|
|
130
140
|
}
|
|
131
141
|
|
|
132
142
|
async function runCommand(parsed: ParsedArgs): Promise<void> {
|
|
133
143
|
const cfg = parsed.config;
|
|
134
|
-
const logger = { logger: console };
|
|
135
144
|
|
|
136
145
|
switch (parsed.command) {
|
|
137
146
|
case 'setup': {
|
|
138
|
-
const
|
|
139
|
-
|
|
147
|
+
const logger = createSetupCommandLogger({ verbose: parsed.verbose, statusCommand: 'moltbank status' });
|
|
148
|
+
try {
|
|
149
|
+
await runSetup(cfg, logger, { authWaitMode: 'blocking' });
|
|
150
|
+
} finally {
|
|
151
|
+
logger.finish();
|
|
152
|
+
}
|
|
140
153
|
return;
|
|
141
154
|
}
|
|
142
155
|
|
|
143
156
|
case 'setup-blocking': {
|
|
144
|
-
|
|
157
|
+
const logger = createSetupCommandLogger({ verbose: parsed.verbose, statusCommand: 'moltbank status' });
|
|
158
|
+
try {
|
|
159
|
+
await runSetup(cfg, logger, { authWaitMode: 'blocking' });
|
|
160
|
+
} finally {
|
|
161
|
+
logger.finish();
|
|
162
|
+
}
|
|
145
163
|
return;
|
|
146
164
|
}
|
|
147
165
|
|
|
166
|
+
case 'status':
|
|
148
167
|
case 'auth-status': {
|
|
168
|
+
const logger = { logger: console };
|
|
149
169
|
printAuthStatus(getSkillDir(cfg), getAppBaseUrl(cfg), logger);
|
|
150
170
|
return;
|
|
151
171
|
}
|
|
152
172
|
|
|
153
173
|
case 'sandbox-setup': {
|
|
174
|
+
const logger = { logger: console };
|
|
154
175
|
const changed = configureSandbox(logger);
|
|
155
176
|
if (changed) {
|
|
156
177
|
recreateSandboxAndRestart(logger);
|
|
@@ -161,6 +182,7 @@ async function runCommand(parsed: ParsedArgs): Promise<void> {
|
|
|
161
182
|
}
|
|
162
183
|
|
|
163
184
|
case 'inject-key': {
|
|
185
|
+
const logger = { logger: console };
|
|
164
186
|
const changed = injectSandboxEnv(getSkillDir(cfg), logger);
|
|
165
187
|
if (changed) {
|
|
166
188
|
recreateSandboxAndRestart(logger);
|
|
@@ -171,6 +193,7 @@ async function runCommand(parsed: ParsedArgs): Promise<void> {
|
|
|
171
193
|
}
|
|
172
194
|
|
|
173
195
|
case 'register': {
|
|
196
|
+
const logger = { logger: console };
|
|
174
197
|
ensureMcporterConfig(getSkillDir(cfg), getAppBaseUrl(cfg), logger);
|
|
175
198
|
return;
|
|
176
199
|
}
|
package/index.ts
CHANGED
|
@@ -32,6 +32,11 @@ interface LoggerApi {
|
|
|
32
32
|
logger: LoggerLike;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
export interface SetupCommandLoggerOptions {
|
|
36
|
+
verbose?: boolean;
|
|
37
|
+
statusCommand?: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
35
40
|
interface ServiceDefinition {
|
|
36
41
|
id: string;
|
|
37
42
|
start: () => void | Promise<void>;
|
|
@@ -66,6 +71,214 @@ export type AuthWaitMode = 'blocking' | 'nonblocking';
|
|
|
66
71
|
const oauthPollers = new Map<string, ReturnType<typeof spawn>>();
|
|
67
72
|
const backgroundFinalizers = new Map<string, ReturnType<typeof spawn>>();
|
|
68
73
|
|
|
74
|
+
class SetupCommandLogger implements LoggerLike {
|
|
75
|
+
private readonly verbose: boolean;
|
|
76
|
+
private readonly statusCommand: string;
|
|
77
|
+
private setupLineOpen = false;
|
|
78
|
+
private authLink = '';
|
|
79
|
+
private authCode = '';
|
|
80
|
+
private authExpiryMinutes: number | null = null;
|
|
81
|
+
private authPromptPrinted = false;
|
|
82
|
+
private waitingLineOpen = false;
|
|
83
|
+
private setupCompletePrinted = false;
|
|
84
|
+
|
|
85
|
+
constructor(options: SetupCommandLoggerOptions = {}) {
|
|
86
|
+
this.verbose = Boolean(options.verbose);
|
|
87
|
+
this.statusCommand = options.statusCommand || 'moltbank status';
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
info(message: string): void {
|
|
91
|
+
this.handle(message, 'info');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
warn(message: string): void {
|
|
95
|
+
this.handle(message, 'warn');
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
finish(): void {
|
|
99
|
+
if (this.setupLineOpen) {
|
|
100
|
+
this.writeRaw('done\n');
|
|
101
|
+
this.setupLineOpen = false;
|
|
102
|
+
}
|
|
103
|
+
if (this.waitingLineOpen && process.stdout.isTTY) {
|
|
104
|
+
this.writeRaw('\n');
|
|
105
|
+
this.waitingLineOpen = false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
private handle(message: string, level: 'info' | 'warn'): void {
|
|
110
|
+
if (this.verbose) {
|
|
111
|
+
this.finish();
|
|
112
|
+
this.writeLine(message, level);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (message === '[moltbank] MoltBank setup starting') {
|
|
117
|
+
this.startSetupLine();
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (this.captureAuthPrompt(message)) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (message === '[moltbank] waiting for approval and polling token...') {
|
|
126
|
+
this.finishSetupLine();
|
|
127
|
+
this.flushAuthPrompt();
|
|
128
|
+
this.showWaitingLine();
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const linkedOrg = this.extractLinkedOrg(message);
|
|
133
|
+
if (linkedOrg) {
|
|
134
|
+
this.finishSetupLine();
|
|
135
|
+
this.flushAuthPrompt();
|
|
136
|
+
this.resolveWaitingLine(`[moltbank] ✓ Linked to org "${linkedOrg}"`, 'info');
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (
|
|
141
|
+
message === '[moltbank] ✗ onboarding code expired or already consumed (invalid_grant)' ||
|
|
142
|
+
message === '[moltbank] ✗ onboarding poll failed or timed out'
|
|
143
|
+
) {
|
|
144
|
+
this.finishSetupLine();
|
|
145
|
+
this.flushAuthPrompt();
|
|
146
|
+
this.resolveWaitingLine('[moltbank] ✗ Code expired. Run `moltbank setup` to get a new code.', 'warn');
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (
|
|
151
|
+
message === '[moltbank] host auth not ready — complete onboarding and run setup again' ||
|
|
152
|
+
message === '[moltbank] sandbox auth not ready — complete onboarding and run setup again' ||
|
|
153
|
+
message === '[moltbank] host auth pending — startup continues without blocking channel startup' ||
|
|
154
|
+
message === '[moltbank] sandbox auth pending — startup continues without blocking channel startup' ||
|
|
155
|
+
message.startsWith('[moltbank] poll detail: ')
|
|
156
|
+
) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (message === '[moltbank] ✓ setup complete') {
|
|
161
|
+
this.finishSetupLine();
|
|
162
|
+
this.clearWaitingLine();
|
|
163
|
+
if (!this.setupCompletePrinted) {
|
|
164
|
+
this.writeLine(`[moltbank] ✓ Setup complete. Run \`${this.statusCommand}\` to verify.`, 'info');
|
|
165
|
+
this.setupCompletePrinted = true;
|
|
166
|
+
}
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (level === 'warn') {
|
|
171
|
+
this.failSetupLine();
|
|
172
|
+
this.clearWaitingLine();
|
|
173
|
+
this.writeLine(message, 'warn');
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
private startSetupLine(): void {
|
|
178
|
+
if (this.setupLineOpen) return;
|
|
179
|
+
this.writeRaw('[moltbank] Setting up MoltBank skill... ');
|
|
180
|
+
this.setupLineOpen = true;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
private finishSetupLine(): void {
|
|
184
|
+
if (!this.setupLineOpen) return;
|
|
185
|
+
this.writeRaw('done\n');
|
|
186
|
+
this.setupLineOpen = false;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
private failSetupLine(): void {
|
|
190
|
+
if (!this.setupLineOpen) return;
|
|
191
|
+
this.writeRaw('failed\n');
|
|
192
|
+
this.setupLineOpen = false;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
private captureAuthPrompt(message: string): boolean {
|
|
196
|
+
const openMatch = message.match(/^\[moltbank\] 1\) Open: (.+)$/);
|
|
197
|
+
if (openMatch) {
|
|
198
|
+
this.authLink = openMatch[1];
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const codeMatch = message.match(/^\[moltbank\] 2\) Enter code: (.+)$/);
|
|
203
|
+
if (codeMatch) {
|
|
204
|
+
this.authCode = codeMatch[1];
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const expiryMatch = message.match(/^\[moltbank\] 3\) Code expires in ~?(\d+) min$/);
|
|
209
|
+
if (expiryMatch) {
|
|
210
|
+
this.authExpiryMinutes = Number(expiryMatch[1]);
|
|
211
|
+
return true;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return (
|
|
215
|
+
message === '[moltbank] ACTION REQUIRED: link this agent to your MoltBank account' ||
|
|
216
|
+
message === '[moltbank] 4) Optional: reply in chat "MoltBank done" for a live status check'
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
private flushAuthPrompt(): void {
|
|
221
|
+
if (this.authPromptPrinted || !this.authLink || !this.authCode) return;
|
|
222
|
+
this.writeLine('[moltbank]', 'info');
|
|
223
|
+
this.writeLine(`[moltbank] Link your agent → ${this.authLink}`, 'info');
|
|
224
|
+
const expirySuffix = this.authExpiryMinutes ? ` (expires in ${this.authExpiryMinutes} min)` : '';
|
|
225
|
+
this.writeLine(`[moltbank] Code: ${this.authCode}${expirySuffix}`, 'info');
|
|
226
|
+
this.writeLine('[moltbank]', 'info');
|
|
227
|
+
this.authPromptPrinted = true;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
private showWaitingLine(): void {
|
|
231
|
+
if (this.waitingLineOpen) return;
|
|
232
|
+
if (process.stdout.isTTY) {
|
|
233
|
+
this.writeRaw('[moltbank] Waiting for approval...');
|
|
234
|
+
this.waitingLineOpen = true;
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
this.writeLine('[moltbank] Waiting for approval...', 'info');
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
private resolveWaitingLine(message: string, level: 'info' | 'warn'): void {
|
|
241
|
+
if (this.waitingLineOpen && process.stdout.isTTY) {
|
|
242
|
+
this.writeRaw(`\r\u001b[2K${message}\n`, level);
|
|
243
|
+
this.waitingLineOpen = false;
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
this.writeLine(message, level);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
private clearWaitingLine(): void {
|
|
250
|
+
if (!this.waitingLineOpen) return;
|
|
251
|
+
if (process.stdout.isTTY) {
|
|
252
|
+
this.writeRaw('\n');
|
|
253
|
+
}
|
|
254
|
+
this.waitingLineOpen = false;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
private extractLinkedOrg(message: string): string | null {
|
|
258
|
+
const match = message.match(
|
|
259
|
+
/^\[moltbank\] ✓ (?:background )?(?:onboarding completed|credentials\.json already available) \(active org: (.+)\)$/
|
|
260
|
+
);
|
|
261
|
+
return match?.[1] ?? null;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
private writeLine(message: string, level: 'info' | 'warn'): void {
|
|
265
|
+
this.writeRaw(`${message}\n`, level);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
private writeRaw(message: string, level: 'info' | 'warn' = 'info'): void {
|
|
269
|
+
const stream = level === 'warn' ? process.stderr : process.stdout;
|
|
270
|
+
stream.write(message);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
export function createSetupCommandLogger(options: SetupCommandLoggerOptions = {}): LoggerApi & { finish(): void } {
|
|
275
|
+
const logger = new SetupCommandLogger(options);
|
|
276
|
+
return {
|
|
277
|
+
logger,
|
|
278
|
+
finish: () => logger.finish()
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
|
|
69
282
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
70
283
|
return typeof value === 'object' && value !== null;
|
|
71
284
|
}
|
|
@@ -282,7 +495,7 @@ function ensureWrapperExecutable(skillDir: string, api: LoggerApi): void {
|
|
|
282
495
|
|
|
283
496
|
const SKILL_FILES = [
|
|
284
497
|
'README.md',
|
|
285
|
-
'
|
|
498
|
+
'SKILL.md',
|
|
286
499
|
'skill.json',
|
|
287
500
|
'install.sh',
|
|
288
501
|
'assets/mcporter.json',
|
|
@@ -337,7 +550,7 @@ function ensureSkillInstalled(
|
|
|
337
550
|
|
|
338
551
|
const filesJson = JSON.stringify(SKILL_FILES).replace(/"/g, '\\"');
|
|
339
552
|
const installNode = run(
|
|
340
|
-
`node --input-type=module -e "import fs from 'fs'; import path from 'path'; const baseRaw=process.argv[1]; const dir=process.argv[2]; const files=JSON.parse(process.argv[3]); const base=baseRaw.endsWith('/') ? baseRaw.slice(0,-1) : baseRaw; fs.mkdirSync(dir,{recursive:true}); for (const f of files){ const
|
|
553
|
+
`node --input-type=module -e "import fs from 'fs'; import path from 'path'; const baseRaw=process.argv[1]; const dir=process.argv[2]; const files=JSON.parse(process.argv[3]); const base=baseRaw.endsWith('/') ? baseRaw.slice(0,-1) : baseRaw; const aliases={ 'SKILL.md':['SKILL.md','skill.md'], 'skill.md':['skill.md','SKILL.md'] }; fs.mkdirSync(dir,{recursive:true}); for (const f of files){ const out=path.join(dir,f); fs.mkdirSync(path.dirname(out),{recursive:true}); let body=null; let lastUrl=''; let lastStatus=''; for (const candidate of (aliases[f] ?? [f])){ const u=base+'/'+candidate; lastUrl=u; const r=await fetch(u); if(r.ok){ body=await r.text(); break; } lastStatus=String(r.status); } if(body===null){ console.error('download failed',lastUrl,lastStatus); process.exit(2);} fs.writeFileSync(out, body,'utf8'); } fs.writeFileSync(path.join(dir,'.install_success'),'ok\\n','utf8');" "${appBaseUrl}" "${skillDir}" "${filesJson}"`,
|
|
341
554
|
{ cwd: dirname(skillDir), silent: true }
|
|
342
555
|
);
|
|
343
556
|
|
|
@@ -1294,7 +1507,7 @@ export async function runSetup(
|
|
|
1294
1507
|
} else if (hostReady) {
|
|
1295
1508
|
api.logger.info('[moltbank] ✓ host ready');
|
|
1296
1509
|
}
|
|
1297
|
-
api.logger.info(`[moltbank] skill: ${skillDir}/
|
|
1510
|
+
api.logger.info(`[moltbank] skill: ${skillDir}/SKILL.md`);
|
|
1298
1511
|
api.logger.info(`[moltbank] mcporter: ${skillDir}/assets/mcporter.json`);
|
|
1299
1512
|
if (sandbox) {
|
|
1300
1513
|
const finalConfig = readOpenclawConfig();
|
|
@@ -1357,19 +1570,15 @@ export default function register(api: PluginApi) {
|
|
|
1357
1570
|
.addCommand(
|
|
1358
1571
|
program
|
|
1359
1572
|
.createCommand('setup')
|
|
1360
|
-
.description('Re-run MoltBank setup
|
|
1573
|
+
.description('Re-run MoltBank setup')
|
|
1361
1574
|
.action(async () => {
|
|
1362
|
-
|
|
1363
|
-
const
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
console.log('[moltbank] optional immediate check: openclaw moltbank auth-status');
|
|
1369
|
-
} else {
|
|
1370
|
-
console.log('[moltbank] setup auth mode: blocking (waiting for OAuth approval)');
|
|
1575
|
+
const verbose = process.argv.includes('--verbose');
|
|
1576
|
+
const logger = createSetupCommandLogger({ verbose, statusCommand: 'openclaw moltbank status' });
|
|
1577
|
+
try {
|
|
1578
|
+
await runSetup(cfg, logger, { authWaitMode: 'blocking' });
|
|
1579
|
+
} finally {
|
|
1580
|
+
logger.finish();
|
|
1371
1581
|
}
|
|
1372
|
-
await runSetup(cfg, { logger: console }, { authWaitMode });
|
|
1373
1582
|
})
|
|
1374
1583
|
)
|
|
1375
1584
|
.addCommand(
|
|
@@ -1377,8 +1586,13 @@ export default function register(api: PluginApi) {
|
|
|
1377
1586
|
.createCommand('setup-blocking')
|
|
1378
1587
|
.description('Re-run full MoltBank setup and wait for OAuth approval')
|
|
1379
1588
|
.action(async () => {
|
|
1380
|
-
|
|
1381
|
-
|
|
1589
|
+
const verbose = process.argv.includes('--verbose');
|
|
1590
|
+
const logger = createSetupCommandLogger({ verbose, statusCommand: 'openclaw moltbank status' });
|
|
1591
|
+
try {
|
|
1592
|
+
await runSetup(cfg, logger, { authWaitMode: 'blocking' });
|
|
1593
|
+
} finally {
|
|
1594
|
+
logger.finish();
|
|
1595
|
+
}
|
|
1382
1596
|
})
|
|
1383
1597
|
)
|
|
1384
1598
|
.addCommand(
|
|
@@ -1408,6 +1622,16 @@ export default function register(api: PluginApi) {
|
|
|
1408
1622
|
}
|
|
1409
1623
|
})
|
|
1410
1624
|
)
|
|
1625
|
+
.addCommand(
|
|
1626
|
+
program
|
|
1627
|
+
.createCommand('status')
|
|
1628
|
+
.description('Show current MoltBank auth state')
|
|
1629
|
+
.action(() => {
|
|
1630
|
+
const appBaseUrl = getAppBaseUrl(cfg);
|
|
1631
|
+
const skillDir = getSkillDir(cfg);
|
|
1632
|
+
printAuthStatus(skillDir, appBaseUrl, { logger: console });
|
|
1633
|
+
})
|
|
1634
|
+
)
|
|
1411
1635
|
.addCommand(
|
|
1412
1636
|
program
|
|
1413
1637
|
.createCommand('auth-status')
|