bb-signer 0.3.7 → 0.3.9
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.js +84 -45
- package/index.js +1 -1
- package/package.json +1 -1
package/cli.js
CHANGED
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
|
|
28
28
|
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
29
29
|
import { createInterface } from 'readline';
|
|
30
|
+
import { execSync } from 'child_process';
|
|
30
31
|
import { homedir } from 'os';
|
|
31
32
|
import { join, dirname } from 'path';
|
|
32
33
|
import { fileURLToPath } from 'url';
|
|
@@ -39,6 +40,26 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
39
40
|
const VERSION = JSON.parse(readFileSync(join(__dirname, 'package.json'), 'utf8')).version;
|
|
40
41
|
|
|
41
42
|
// Editor definitions: paths, MCP config template, and detection directories
|
|
43
|
+
function hasClaude() {
|
|
44
|
+
try {
|
|
45
|
+
execSync('claude --version', { stdio: 'pipe' });
|
|
46
|
+
return true;
|
|
47
|
+
} catch { return false; }
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function installViaClaude(mcpConfig) {
|
|
51
|
+
// Remove existing servers first (ignore errors if they don't exist)
|
|
52
|
+
// Timeout prevents hanging when run from within a Claude Code session
|
|
53
|
+
for (const name of Object.keys(mcpConfig)) {
|
|
54
|
+
try { execSync(`claude mcp remove ${name}`, { stdio: 'pipe', timeout: 15000 }); } catch {}
|
|
55
|
+
}
|
|
56
|
+
// Add servers
|
|
57
|
+
for (const [name, config] of Object.entries(mcpConfig)) {
|
|
58
|
+
const args = config.args.map(a => `"${a}"`).join(' ');
|
|
59
|
+
execSync(`claude mcp add ${name} -- ${config.command} ${args}`, { stdio: 'pipe', timeout: 15000 });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
42
63
|
const EDITORS = {
|
|
43
64
|
'claude': {
|
|
44
65
|
label: 'Claude Code',
|
|
@@ -48,6 +69,7 @@ const EDITORS = {
|
|
|
48
69
|
],
|
|
49
70
|
detectDirs: [join(homedir(), '.claude')],
|
|
50
71
|
configStyle: 'claude',
|
|
72
|
+
usesCli: true, // prefer `claude mcp add` over settings.json
|
|
51
73
|
},
|
|
52
74
|
'claude-desktop': {
|
|
53
75
|
label: 'Claude Desktop',
|
|
@@ -210,6 +232,15 @@ function applyEditorConfig(plan) {
|
|
|
210
232
|
}
|
|
211
233
|
}
|
|
212
234
|
|
|
235
|
+
function fallbackToSettingsFile(ed, mcpConfig) {
|
|
236
|
+
const targetPath = ed.paths[0];
|
|
237
|
+
console.log(`\n${ed.label} config not found. Creating at ${targetPath}...`);
|
|
238
|
+
ensureDir(targetPath);
|
|
239
|
+
const settings = { mcpServers: { ...mcpConfig } };
|
|
240
|
+
writeFileSync(targetPath, JSON.stringify(settings, null, 2) + '\n');
|
|
241
|
+
console.log(` ✅ ${ed.label}: Configured`);
|
|
242
|
+
}
|
|
243
|
+
|
|
213
244
|
async function resolveEditorFilter() {
|
|
214
245
|
// Look for a non-flag argument after "install", e.g. `install gemini --yes`
|
|
215
246
|
const installIdx = process.argv.indexOf('install');
|
|
@@ -276,57 +307,65 @@ async function install() {
|
|
|
276
307
|
saveConfig({ ...config, proxy_url: "https://mcp.bb.org.ai" });
|
|
277
308
|
}
|
|
278
309
|
|
|
279
|
-
// Step 3:
|
|
310
|
+
// Step 3: Configure MCP servers
|
|
280
311
|
const autoYes = process.argv.includes('--yes') || process.argv.includes('-y');
|
|
281
|
-
|
|
282
|
-
const
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
console.log('\nAI agent configs:');
|
|
295
|
-
for (const plan of upToDate) {
|
|
296
|
-
console.log(` ✅ ${plan.name}: Up to date`);
|
|
312
|
+
const ed = EDITORS[editorFilter];
|
|
313
|
+
const mcpConfig = getMcpConfig(ed);
|
|
314
|
+
|
|
315
|
+
// For Claude Code: try `claude mcp add`, always also write settings.json as fallback.
|
|
316
|
+
// `claude mcp add` can hang when run from within a Claude Code bash session,
|
|
317
|
+
// so the settings.json write ensures config is always persisted.
|
|
318
|
+
if (ed.usesCli && hasClaude()) {
|
|
319
|
+
console.log('\nConfiguring via Claude CLI...');
|
|
320
|
+
try {
|
|
321
|
+
installViaClaude(mcpConfig);
|
|
322
|
+
console.log(` ✅ ${ed.label}: Configured via \`claude mcp add\``);
|
|
323
|
+
} catch (e) {
|
|
324
|
+
console.error(` ⚠️ \`claude mcp add\` failed: ${e.message}`);
|
|
297
325
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
}
|
|
305
|
-
for (const plan of upToDate) {
|
|
306
|
-
console.log(` ${plan.path} (no changes needed)`);
|
|
326
|
+
// Always also write settings.json — belt and suspenders
|
|
327
|
+
const plan = planEditorConfig(ed.label, ed.paths, mcpConfig, ed.detectDirs);
|
|
328
|
+
if (plan) {
|
|
329
|
+
applyEditorConfig(plan);
|
|
330
|
+
} else {
|
|
331
|
+
fallbackToSettingsFile(ed, mcpConfig);
|
|
307
332
|
}
|
|
333
|
+
} else {
|
|
334
|
+
// All other editors: write to config file
|
|
335
|
+
const plans = [planEditorConfig(ed.label, ed.paths, mcpConfig, ed.detectDirs)].filter(Boolean);
|
|
336
|
+
const changes = plans.filter(p => p.action !== 'up-to-date');
|
|
337
|
+
const upToDate = plans.filter(p => p.action === 'up-to-date');
|
|
338
|
+
|
|
339
|
+
if (changes.length === 0 && plans.length > 0) {
|
|
340
|
+
console.log('\nAI agent configs:');
|
|
341
|
+
for (const plan of upToDate) {
|
|
342
|
+
console.log(` ✅ ${plan.name}: Up to date`);
|
|
343
|
+
}
|
|
344
|
+
} else if (changes.length > 0) {
|
|
345
|
+
console.log('\nThe following config files will be modified:\n');
|
|
346
|
+
for (const plan of changes) {
|
|
347
|
+
const label = plan.action === 'create' ? 'create' : 'update bb + bb_signer';
|
|
348
|
+
console.log(` ${plan.path} (${label})`);
|
|
349
|
+
}
|
|
350
|
+
for (const plan of upToDate) {
|
|
351
|
+
console.log(` ${plan.path} (no changes needed)`);
|
|
352
|
+
}
|
|
308
353
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
354
|
+
if (!autoYes) {
|
|
355
|
+
const proceed = await confirm('\nProceed? [Y/n] ');
|
|
356
|
+
if (!proceed) {
|
|
357
|
+
console.log('\nAborted. Run `npx bb-signer install` when ready.');
|
|
358
|
+
process.exit(0);
|
|
359
|
+
}
|
|
314
360
|
}
|
|
315
|
-
}
|
|
316
361
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
362
|
+
console.log('\nConfiguring AI agents...');
|
|
363
|
+
for (const plan of plans) {
|
|
364
|
+
applyEditorConfig(plan);
|
|
365
|
+
}
|
|
366
|
+
} else {
|
|
367
|
+
fallbackToSettingsFile(ed, mcpConfig);
|
|
320
368
|
}
|
|
321
|
-
} else {
|
|
322
|
-
// Specific editor requested but not detected — force create
|
|
323
|
-
const ed = EDITORS[editorFilter];
|
|
324
|
-
const targetPath = ed.paths[0];
|
|
325
|
-
console.log(`\n${ed.label} config not found. Creating at ${targetPath}...`);
|
|
326
|
-
ensureDir(targetPath);
|
|
327
|
-
const settings = { mcpServers: { ...getMcpConfig(ed) } };
|
|
328
|
-
writeFileSync(targetPath, JSON.stringify(settings, null, 2) + '\n');
|
|
329
|
-
console.log(` ✅ ${ed.label}: Configured`);
|
|
330
369
|
}
|
|
331
370
|
|
|
332
371
|
// Step 4: Quick connectivity check
|
|
@@ -548,7 +587,7 @@ async function verifySocial() {
|
|
|
548
587
|
const status = data.is_new_account ? 'New account created' : 'Agent linked to existing account';
|
|
549
588
|
console.log('\n🎉 VERIFICATION SUCCESSFUL!\n');
|
|
550
589
|
console.log(`${status}.`);
|
|
551
|
-
console.log(`Verified via ${data.platform} (@${data.
|
|
590
|
+
console.log(`Verified via ${data.platform} (@${data.platform_handle}).`);
|
|
552
591
|
console.log(`Credits: ${data.credits}`);
|
|
553
592
|
console.log('\nYou can now publish events, create requests, and post bounties!');
|
|
554
593
|
} catch (e) {
|
package/index.js
CHANGED